.net Jwt 鉴权,且自定义出参 +Swagger 验证

.net core  使用 System.IdentityModel.Tokens.Jwt  来实现JWT 鉴权。

可自定义鉴权失败的出参。支持Swagger验证

话不多说,直接上码

第一步: JWT实现servic:DiJWTServiceCollectionExtensions

/// <summary>
    /// jwt 用户权限
    /// </summary>
    public static class JwtRole
    {
        /// <summary>
        /// 用户登录的
        /// </summary>
        public const string UserInfo = "UserInfo";

        /// <summary>
        /// 设备登录的
        /// </summary>
        public const string DeviceInfo = "DeviceInfo";
    }


    /// <summary>
    /// 微软 System.IdentityModel.Tokens.Jwt 
    /// </summary>
    public class JwtService
    {

        private TokenValidationParameters _tokenValidationParameters { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tokenValidationParameters"></param>
        public JwtService(TokenValidationParameters tokenValidationParameters)
        {
            _tokenValidationParameters = tokenValidationParameters;
        }


        /// <summary>
        /// 生产JWTToken
        /// </summary>
        /// <param name="claim"></param>
        /// <param name="role"></param>
        /// <param name="expires">过期时间</param>
        /// <returns></returns>
        public string GenerateJwtToken(Claim claim, string role, DateTime expires)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                      claim,
                      new Claim(ClaimTypes.Role,role)
                }),
                Expires = expires,
                SigningCredentials = new SigningCredentials(_tokenValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }


        /// <summary>
        ///  验证token是否合理,返回对应的值
        /// </summary>
        /// <param name="authenticationToken"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool ValidatedJwtToken(string authenticationToken, out ClaimsPrincipal user)
        {
            bool result = false;
            user = null;
            try
            {

                if (string.IsNullOrEmpty(authenticationToken))
                {
                    return false;
                }
                //校验并解析token
                var handler = new JwtSecurityTokenHandler();
                var claimsPrincipal = handler.ValidateToken(authenticationToken, _tokenValidationParameters,
                    out SecurityToken validatedToken);//validatedToken:解密后的对象

                //user = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); //获取payload中的数据 
                result = claimsPrincipal.Identity.IsAuthenticated;
                user = claimsPrincipal;

            }
            catch (SecurityTokenExpiredException stee)
            {
                //表示过期 
            }
            catch (SecurityTokenException ste)
            {
                //表示token错误

            }
            catch (Exception e)
            {

            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="authenticationToken"></param>
        /// <param name="payload"></param>
        /// <returns></returns>
        public bool ValidatedJwtToken(string authenticationToken, out object payload)
        {
            bool result = false;
            payload = null;
            try
            {

                if (string.IsNullOrEmpty(authenticationToken))
                {
                    return false;
                }
                //校验并解析token
                var handler = new JwtSecurityTokenHandler();
                var claimsPrincipal = handler.ValidateToken(authenticationToken, _tokenValidationParameters,
                    out SecurityToken validatedToken);//validatedToken:解密后的对象

                //user = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); //获取payload中的数据 
                result = claimsPrincipal.Identity.IsAuthenticated;
                var jwtVT = ((JwtSecurityToken)validatedToken);
                payload = jwtVT.Payload.GetValueOrDefault(ClaimTypes.Authentication) ?? jwtVT.Payload.GetValueOrDefault(ClaimTypes.UserData);
            }
            catch (SecurityTokenExpiredException stee)
            {
                //表示过期 
                Console.WriteLine("Token过期");
            }
            catch (SecurityTokenException ste)
            {
                //表示token错误
                Console.WriteLine("Token错误");

            }
            catch (Exception e)
            {

            }
            return result;
        }
    }



    public static class DiJWTServiceCollectionExtensions
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddJwtService(this IServiceCollection services,string serkey)
        {
            var tokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = false,//是否验证Issuer
                ValidIssuer = "ApiServer",
                ValidateAudience = false,//是否验证Audience
                ValidateLifetime = true,//是否验证失效时间
                ClockSkew = TimeSpan.FromSeconds(60),
                ValidateIssuerSigningKey = true,//是否验证SecurityKey
                                                //ValidAudience = Const.Domain,//Audience
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(serkey))//拿到SecurityKey
            };
            //将此配置 注入服务,因为还有其他地方需要使用
            services.AddSingleton(tokenValidationParameters);

            //注册 自定义服务
            services.AddSingleton<JwtService>();
            return services;
        }
    }

第二步:自定义过滤器  MyAuthorizeFilter

可自定义Headers,Query,cookies,token的入参名称:如下代码

     var token = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last()
                   ?? context.HttpContext.Request.Headers["X-Token"].FirstOrDefault()
                   ?? context.HttpContext.Request.Query["Token"].FirstOrDefault()
                   ?? context.HttpContext.Request.Cookies["Token"];

当然大家可随意设置,只需要和前端约定好即可。

 /// <summary>
    /// 只为重写 OnAuthorizationAsync  自定义返回数据消息
    /// </summary>
    public class MyAuthorizeFilter : IAsyncAuthorizationFilter
    {
        private JwtService _jwtService { get; set; }
        /// <summary>
        ///
        /// </summary>
        /// <param name="jwtService"></param>
        public MyAuthorizeFilter(JwtService jwtService)
        {
            _jwtService = jwtService;
        }

        private static bool HasAllowAnonymous(AuthorizationFilterContext context)
        {
            var filters = context.Filters;
            for (var i = 0; i < filters.Count; i++)
            {
                if (filters[i] is IAllowAnonymousFilter)
                {
                    return true;
                }
            }
            // When doing endpoint routing, MVC does not add AllowAnonymousFilters for AllowAnonymousAttributes that
            // were discovered on controllers and actions. To maintain compat with 2.x,
            // we'll check for the presence of IAllowAnonymous in endpoint metadata.
            var endpoint = context.HttpContext.GetEndpoint();
            if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (!context.IsEffectivePolicy(this))
            {
                return;
            }
            // Allow Anonymous skips all authorization
            if (HasAllowAnonymous(context))
            {
                return;
            }
            else
            {
                var token = context.HttpContext.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last()
                   ?? context.HttpContext.Request.Headers["X-Token"].FirstOrDefault()
                   ?? context.HttpContext.Request.Query["Token"].FirstOrDefault()
                   ?? context.HttpContext.Request.Cookies["Token"];

                ClaimsPrincipal user = context.HttpContext.User;
                if (_jwtService.ValidatedJwtToken(token, out user))
                {
                    //验证通过,验证成功  赋值给User
                    context.HttpContext.User = user;
                }
                else
                {
                    context.Result = new JsonResult(new
                    {
                        Code = 401,
                        Message = "没有权限"
                    });
                }
            }
            //Console.WriteLine(JsonHelper.SerializeObject(context.HttpContext.Items));
        }
    }

 第三步:Startup 使用 

 第四步:添加OAuthController.cs   获取token 方法,以及测试方法

 

 展示效果:

没有token 之前,调用Get接口  提示无权限。

为自定义出参哦,可以和自己项目整体出参自定义一致。

{
  "code": 401,
  "message": "没有权限"
}

 获取token

 点击下图所示第一步:将上图token填入文本框中。点击绿色按钮,最后点击close按钮。

 重新执行get方法,就得到我们想要的了。

 源码地址:

https://github.com/BigMaJx/OOPDemo/blob/master/Api/Controllers/OAuthController.cs

https://github.com/BigMaJx/OOPDemo/blob/master/Api/SecuritysDI/

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值