欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

.net core webapi 的 JWT 授权认证

程序员文章站 2024-01-29 17:46:04
...

传统的授权认证:

传统验证基于CookiesSession;但是由于http是无状态的(第一次和第二次发送的http请求没有任何区别),所以这种模式有很多局限,比如在多服务器集群时就无法使用;
和asp.net相比,core的不同,是在实例化类之前,就先进行身份认证,身份认证完了以后,再完成授权;
.net core webapi 的 JWT 授权认证

基于Token的授权认证

下边是基于token验证的流程图:
.net core webapi 的 JWT 授权认证

  • 授权服务器发送的token由私钥加密;
  • API得到的token,用公钥解密;


    Token令牌的组成:
    最终API如何能确定这个token就是授权服务器发来的呢?这个就是看签名。对得到的token,可以通过jwt.io网站来进行解读。
    .net core webapi 的 JWT 授权认证

具体完成JWT授权

1.新建一个授权API项目,然后新建一个授权控制器;
.net core webapi 的 JWT 授权认证
2.为了实现解耦,新建一个服务类,完成token的颁发:
.net core webapi 的 JWT 授权认证
3.控制器的代码如下


    [Route("api")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    { 
        #region MyRegion  //region是为了方便折叠
        private ILogger<AuthenticationController> _logger = null;
        private IJWTService _iJWTService = null;
        private readonly IConfiguration _iConfiguration;
        public AuthenticationController(ILoggerFactory factory,//此处做了三个依赖注入;
            ILogger<AuthenticationController> logger,
            IConfiguration configuration
            , IJWTService service)
        {
            this._logger = logger;
            this._iConfiguration = configuration;
            this._iJWTService = service;
        }
        #endregion
        [Route("Get")]
        [HttpGet]
        public IEnumerable<int> Get()
        {
            return new List<int>() { 1, 2, 3, 4, 6, 7 };
        }

        [Route("Login")]  //log是日志,login是注册;
        [HttpGet]
        public string Login(string name, string password)
        {
            ///这里肯定是需要去连接数据库做数据校验
            if ("Richard".Equals(name) && "123456".Equals(password))//应该数据库
            {
                string token = this._iJWTService.GetToken(name);//调用后台的个体Token方法
                                                                //,这样就可以获取token了。
                return JsonConvert.SerializeObject(new  //把结果转化为Json格式返回。
                {
                    result = true,
                    token
                });
            }
            else
            {
                return JsonConvert.SerializeObject(new
                {
                    result = false,
                    token = ""
                });
            }}}

4.获取token的类的代码如下:首先声明一个接口,然后再实现这个接口
声明接口

public interface IJWTService
    {
        string GetToken(string UserName);
    }

实现这个接口

public class JWTService : IJWTService
    {
        private readonly IConfiguration _configuration;
        public JWTService(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public string GetToken(string UserName)
        {
            Claim[] claims = new[]  //claim这里面包含的就是Token中的载荷的信息;
            {
               new Claim(ClaimTypes.Name, UserName),
               new Claim("NickName","Richard"),
               new Claim("Role","Administrator"),//传递其他信息  
               new Claim("abc","abccc")
               //new Claim
            };
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"]));
            //从配置文件中读去key(养成良好的编码习惯,把配置文件,尽量写在配置文件里)
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            //对key进行加密;
            /**
             *  Claims (Payload)
                Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,
                下面节选一些字段:
                iss: The issuer of the token,token 是给谁的
                sub: The subject of the token,token 主题
                exp: Expiration Time。 token 过期时间,Unix 时间戳格式
                iat: Issued At。 token 创建时间, Unix 时间戳格式
                jti: JWT ID。针对当前 token 的唯一标识
                除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
             * */
            var token = new JwtSecurityToken(    //创建新的token
                issuer: _configuration["issuer"],
                audience: _configuration["audience"],
                claims: claims,
                expires: DateTime.Now.AddMinutes(5),//5分钟有效期
                signingCredentials: creds);
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            //生成token需要引用Tokens.jwt的安装包
            return returnToken;
        }
    }

配置文件的声明:
.net core webapi 的 JWT 授权认证

5.新建受保护的API

在startup里面配置授权服务:

             #region JWT鉴权授权
            //1.Nuget引入程序包:Microsoft.AspNetCore.Authentication.JwtBearer 
            //services.AddAuthentication();//禁用  
            var ValidAudience = this.Configuration["audience"];
            var ValidIssuer = this.Configuration["issuer"];
            var SecurityKey = this.Configuration["SecurityKey"];
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)  //默认授权机制名称;                                      
                     .AddJwtBearer(options =>
                     {
                         options.TokenValidationParameters = new TokenValidationParameters
                         {
                             ValidateIssuer = true,//是否验证Issuer
                             ValidateAudience = true,//是否验证Audience
                             ValidateLifetime = true,//是否验证失效时间
                             ValidateIssuerSigningKey = true,//是否验证SecurityKey
                             ValidAudience = ValidAudience,//Audience
                             ValidIssuer = ValidIssuer,//Issuer,这两项和前面签发jwt的设置一致  表示谁签发的Token
                             IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey))//拿到SecurityKey
                             //AudienceValidator = (m, n, z) =>
                             //{
                             //    return m != null && m.FirstOrDefault().Equals(this.Configuration["audience"]);
                             //},//自定义校验规则,可以新登录后将之前的无效 
                         };});
                             #endregion

6.在中间件管道里面添加身份认证和授权的中间件:

            app.UseAuthentication();//身份认证
            app.UseAuthorization();//授权

7.在需要保护的API上添加 [Authorize] 属性

       [Authorize] //Microsoft.AspNetCore.Authorization
        public IActionResult GetAuthorizeData()
        { 
          var Name = base.HttpContext.AuthenticateAsync().Result.Principal.Claims.FirstOrDefault(a=>a.Type.Equals("Name"))?.Value;

            Console.WriteLine($"this is Name {Name}"); 
            return new JsonResult(new
            {
                Data = "已授权",
                Type = "GetAuthorizeData" 
                //Claims=Newtonsoft.Json.JsonConvert.SerializeObject(Claims)
            });
        }

8.也可以直接添加到类上,对命名空间里,所有的方法都授权认证,多例外不需要的,添加 [AllowAnonymous] 允许匿名属性;

题外话:
#region这个语法,是用来方便折叠的。
参考资料联系侵删;

相关标签: .net core c#