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, "66666666666@qq.com"),
            //};

            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]
posted @ 2023-03-22 16:21  雨水的命运  阅读(92)  评论(0编辑  收藏  举报