1. 程式人生 > 實用技巧 >net core 3.1 jwt認證--1

net core 3.1 jwt認證--1

net core 3.1 jwt認證

  1. 首先在Visual Studio中建立一個WebApi專案;
  2. 引入nuget包:Microsoft.AspNetCore.Authentication.JwtBearer
  3. 在appsetting.json中配置jwt引數
Copy
"tokenConfig": {
    "secret": "D96BFA5B-F2AF-45BC-9342-5A55C3F9BBB0",
    "issuer": "test.cn",
    "audience": "test",
    "accessExpiration": 30,
    "refreshExpiration": 60
  }
  1. 編寫對應的token物件:
Copy
using Newtonsoft.Json;

namespace JwtDemo
{
    public class TokenManagement
    {
        [JsonProperty("secret")]
        public string Secret { get; set; }

        [JsonProperty("issuer")]
        public string Issuer { get; set; }

        [JsonProperty("audience")]
        public string Audience { get; set; }

        [JsonProperty("accessExpiration")]
        public int AccessExpiration { get; set; }

        [JsonProperty("refreshExpiration")]
        public int RefreshExpiration { get; set; }
    }
}
  1. 在Startup中配置啟用token認證
Copy
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using static JwtDemo.LoginRequestDTO;

namespace JwtDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.Configure<TokenManagement>(Configuration.GetSection("tokenConfig"));

            var token = Configuration.GetSection("tokenConfig").Get<TokenManagement>();

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                //Token Validation Parameters
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    //獲取或設定要使用的Microsoft.IdentityModel.Tokens.SecurityKey用於簽名驗證。
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.
                    GetBytes(token.Secret)),
                    //獲取或設定一個System.String,它表示將使用的有效發行者檢查代幣的發行者。
                    ValidIssuer = token.Issuer,
                    //獲取或設定一個字串,該字串表示將用於檢查的有效受眾反對令牌的觀眾。
                    ValidAudience = token.Audience,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                };
            });
            services.AddScoped<IAuthenticateService, TokenAuthenticationService>();
            services.AddScoped<IUserService, UserService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseAuthentication();
            
            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

  1. 編寫認證服務介面及服務類
Copy
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.ComponentModel.DataAnnotations;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace JwtDemo
{
    public interface IAuthenticateService
    {
        bool IsAuthenticated(LoginRequestDTO request, out string token);
    }

    public class LoginRequestDTO
    {
        [Required]
        [JsonProperty("username")]
        public string Username { get; set; }


        [Required]
        [JsonProperty("password")]
        public string Password { get; set; }

        /// <summary>
        /// token認證服務
        /// </summary>
        public class TokenAuthenticationService : IAuthenticateService
        {
            private readonly IUserService _userService;
            private readonly TokenManagement _tokenManagement;
            public TokenAuthenticationService(IUserService userService, IOptions<TokenManagement> tokenManagement)
            {
                _userService = userService;
                _tokenManagement = tokenManagement.Value;
            }
            public bool IsAuthenticated(LoginRequestDTO request, out string token)
            {
                token = string.Empty;
                if (!_userService.IsValid(request))
                    return false;
                var claims = new[]
                {
                new Claim(ClaimTypes.Name,request.Username)
            };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenManagement.Secret));
                var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var jwtToken = new JwtSecurityToken(_tokenManagement.Issuer, _tokenManagement.Audience, claims,
                    expires: DateTime.Now.AddMinutes(_tokenManagement.AccessExpiration),
                    signingCredentials: credentials);
                token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
                return true;
            }
        }

    }

}

  1. 自定義認證介面及類IUserService和UserService,模擬驗證密碼的過程,這個需要在Startup中配置注入服務
Copy
namespace JwtDemo
{
    public interface IUserService
    {
        bool IsValid(LoginRequestDTO req);
    }

    public class UserService : IUserService
    {
        //模擬測試,預設都是人為驗證有效
        public bool IsValid(LoginRequestDTO req)
        {
            return true;
        }
    }
}
  1. 新增AuthenticationController,用於根據使用者名稱和密碼獲取token
Copy
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace JwtDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        private readonly IAuthenticateService _authService;
        public AuthenticationController(IAuthenticateService authService)
        {
            this._authService = authService;
        }

        [AllowAnonymous]
        [HttpPost, Route("requestToken")]
        public ActionResult RequestToken([FromBody] LoginRequestDTO request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest("Invalid Request");
            }

            string token;
            if (_authService.IsAuthenticated(request, out token))
            {
                return Ok(token);
            }

            return BadRequest("Invalid Request");
        }

    }
}
  1. 測試:測試之前先給WeatherForecastController加上[Authorize],身份驗證之後才能訪問
  • 先訪問https://localhost:44324/weatherforecast,結果為401,未授權,

  • 下面請求token:

獲取到token:

帶token訪問被保護的webapi:

成功獲取到webapi資料:

通過學習瞭解了基本的jwt認證的使用方法
學會了在Fiddler中測試webapi
原始碼:https://gitee.com/Alexander360/LearnIdentity/tree/master/LearnIdentity