ASP.NET Core Jwt 認證

安裝Microsoft.AspNetCore.Authentication.JwtBearerNuget包

appsettings.json中,添加JWT的配置,注意SecretKey不能設置成太短的純數字,不然要報錯

  "JWT": {
    "Issuer": "AudienceUpgrade", //發行人
    "Audience": "UpgradeService", //擁有者
    "SecretKey": "900BA04D853C4DDF9CBF8B2B406EB4B6", //16位以上
    "Expires": 7 //過期時間 單位:天
  }

添加Jwt服務

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true, //是否驗證Issuer
        ValidIssuer = builder.Configuration["Jwt:Issuer"], //發行人Issuer
        ValidateAudience = true, //是否驗證Audience
        ValidAudience = builder.Configuration["Jwt:Audience"], //訂閱人Audience
        ValidateIssuerSigningKey = true, //是否驗證SecurityKey
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:SecretKey"])), //SecurityKey
        ValidateLifetime = true, //是否驗證失效時間
        ClockSkew = TimeSpan.FromSeconds(30), //過期時間容錯值,解決服務器端時間不同步問題(秒)
        RequireExpirationTime = true,
    };
    //自定義認證不過的返回值
    options.Events = new JwtBearerEvents
    {
        OnChallenge = async context =>
        {
            context.HandleResponse();
            context.Response.ContentType = "application/json;charset=utf-8";
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            await context.Response.WriteAsync("{\"message\":\"Unauthorized\",\"success\":false}");
        }
    };
});

啓用認證

app.UseAuthentication();
app.UseAuthorization();

添加一個JWT幫助類

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Text;

namespace WebApplication2
{
    public class TokenHelper
    {
        private readonly IConfiguration _configuration;
        public TokenHelper(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        /// <summary>
        /// 創建加密JwtToken
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string CreateJwtToken<T>(T t)
        {
            // 定義用戶信息
            //var claims = new Claim[]
            //{
            //    new Claim(ClaimTypes.Name, "123456"),
            //    new Claim(JwtRegisteredClaimNames.Email, "[email protected]"),
            //};

            var claimList = new List<Claim>();
            foreach (var item in typeof(T).GetProperties()) claimList.Add(new Claim(item.Name, item.GetValue(t)!.ToString()!));

            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:SecretKey"]));

            var expires = Convert.ToDouble(_configuration["JWT:Expires"]);

            var algorithm = SecurityAlgorithms.HmacSha256;//選擇加密算法

            var signingCredentials = new SigningCredentials(secretKey, algorithm);
            JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
               _configuration["JWT:Issuer"],     //Issuer
                _configuration["JWT:Audience"],   //Audience
                claims: claimList,
                DateTime.Now,                    //notBefore
                DateTime.Now.AddDays(expires),   //expires
                signingCredentials               //Credentials
                );
            string jwtToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
            return jwtToken;
        }

        /// <summary>
        /// 通過Token獲取對象信息,實體類字段必須全部是string類型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Token"></param>
        /// <returns></returns>
        public T GetTokenObj<T>(string Token)
        {
            var jwt = Token.Replace("Bearer ", string.Empty).TrimStart();
            Type t = typeof(T);
            object obj = Activator.CreateInstance(t)!;
            var jwtInfo = new JwtSecurityTokenHandler().ReadJwtToken(jwt);
            foreach (var item in jwtInfo.Claims)
            {
                PropertyInfo _Property = t.GetProperty(item.Type);
                if (_Property != null && _Property.CanRead)
                    _Property.SetValue(obj, item.Value, null);
            }
            return (T)obj;
        }

        /// <summary>
        /// Token是否是符合要求的標準 Json Web 令牌
        /// </summary>
        /// <param name="tokenStr"></param>
        /// <returns></returns>
        public bool IsCanReadToken(ref string tokenStr)
        {
            if (string.IsNullOrWhiteSpace(tokenStr) || tokenStr.Length < 7)
                return false;
            if (!tokenStr.Substring(0, 6).Equals(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme))
                return false;
            tokenStr = tokenStr.Substring(7);
            bool isCan = new JwtSecurityTokenHandler().CanReadToken(tokenStr);

            return isCan;
        }
    }
}

注入生命週期

builder.Services.AddSingleton<TokenHelper>();

使用JWT

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

namespace WebApplication2.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly TokenHelper _tokenHelper;
        public WeatherForecastController(TokenHelper tokenHelper)
        {
            _tokenHelper = tokenHelper;
        }

        [Authorize]
        [HttpGet("GetWeatherForecast")]
        public string Get()
        {
            string tokenStr = Request.Headers["Authorization"].ToString();
            //獲取相關信息,實體類字段必須全部是string類型
            var obj = _tokenHelper.GetTokenObj<Login>(tokenStr);
            return JsonSerializer.Serialize(obj);
        }

        /// <summary>
        /// 登錄
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("Login")]
        public string Login()
        {
            var t = new Login { Id=Guid.NewGuid().ToString() };
            return _tokenHelper.CreateJwtToken(t);
        }
    }
    public class Login
    {
        public string Id { get; set; }
    }
}

控制器加上特性

//添加Jwt認證
[Authorize]
//取消認證
[AllowAnonymous]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章