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

.NET Core的JWT认证的学习

程序员文章站 2023-11-14 09:38:16
今天学习下JWT,遇到了两个坑爹问题,这里记录下。在 ASP.NET Core 中,授权的设置方式有两种,可以使用角色,也可以使用策略,这里也将简单举例角色、策略的使用。 JWT这里不做介绍,如果想了解更多,请看https://www.jianshu.com/p/a12fc67c9e05,https ......

今天学习下jwt,遇到了两个坑爹问题,这里记录下。在 asp.net core 中,授权的设置方式有两种,可以使用角色,也可以使用策略,这里也将简单举例角色、策略的使用。

jwt这里不做介绍,如果想了解更多,请看https://www.jianshu.com/p/a12fc67c9e05,https://www.cnblogs.com/createmyself/p/11123023.html ,这两篇都讲解的很好,这里只写实际的使用和遇到的问题。

1. jwt的secretkey必须16位以上

jwt中key必须16位以上,否则长度不够会抛出异常,异常代码如下

system.argumentoutofrangeexception
  hresult=0x80131502
  message=idx10603: decryption failed. keys tried: '[pii is hidden. for more details, see https://aka.ms/identitymodel/pii.]'.
exceptions caught:
 '[pii is hidden. for more details, see https://aka.ms/identitymodel/pii.]'.
token: '[pii is hidden. for more details, see https://aka.ms/identitymodel/pii.]' 
  source=microsoft.identitymodel.tokens
  stacktrace:
   at microsoft.identitymodel.tokens.symmetricsignatureprovider..ctor(securitykey key, string algorithm, boolean willcreatesignatures)
....................

2.获取token之后,一直401unauthorized

在startup.cs中的configure中添加app.useauthentication();新创建.net core项目的时候,会自动添加授权app.useauthorization();但是jwt其实是一种认证,准确;来说是登录的过程,需要用户名和密码的认证。

例如:你要登陆论坛,输入用户名张三,密码1234,密码正确,证明你张三确实是张三,这就是 认证authentication;那么是否有删除添加等的操作,这就是授权authorization

3.jwttoken的获取

//appsettings.json中增加配置信息
"jwtsettings": {
    "issuer": "https://localhost:44378/",
    "audience": "https://localhost:44378/",
    "secretkey": "1234567890123456"
  }
// startup.cs中增加jwt的设置           
            services.addauthentication(options =>
            {
                //认证middleware配置
                options.defaultauthenticatescheme = jwtbearerdefaults.authenticationscheme;
                options.defaultchallengescheme = jwtbearerdefaults.authenticationscheme;
            })
            .addjwtbearer(o =>
            {
                //主要是jwt  token参数设置
                o.tokenvalidationparameters = new tokenvalidationparameters
                {
                    //token颁发机构
                    validissuer = jwtsettings.issuer,
                    //颁发给谁
                    validaudience = jwtsettings.audience,
                    //这里的key要进行加密,需要引用microsoft.identitymodel.tokens
                    issuersigningkey = new symmetricsecuritykey(encoding.utf8.getbytes(jwtsettings.secretkey)),
                    validateissuersigningkey = true,
                    //是否验证token有效期,使用当前时间与token的claims中的notbefore和expires对比
                    validatelifetime = true,
                    //允许的服务器时间偏移量
                    clockskew = timespan.zero

                };
            });
// controller中获取token       
        [httppost]
        public iactionresult token(loginmodel login)
        {
            _logger.loginformation($"获取token:user:{login.user}");
            if (string.isnullorempty(login.user) || string.isnullorempty(login.password))//判断账号密码是否正确
            {
                return badrequest();
            }


            var claim = new list<claim>{
                    new claim(claimtypes.name,login.user),
                    new claim(claimtypes.role,"test")
                };

            //建立增加策略的授权
            if (login.user == "test") claim.add(new claim("test", "test"));
            if (login.user == "test1") claim.add(new claim("test", "test1"));
            if (login.user == "test2") claim.add(new claim("test", "test2"));
            if (login.user == "test3") claim.add(new claim("test", "test3"));

            //对称秘钥
            var key = new symmetricsecuritykey(encoding.utf8.getbytes(_jwtsettings.secretkey));
            //签名证书(秘钥,加密算法)
            var creds = new signingcredentials(key, securityalgorithms.hmacsha256);

            //生成token  [注意]需要nuget添加microsoft.aspnetcore.authentication.jwtbearer包,并引用system.identitymodel.tokens.jwt命名空间
            var token = new jwtsecuritytoken(_jwtsettings.issuer, _jwtsettings.audience, claim, datetime.now, datetime.now.addminutes(30), creds);

            return ok(new { token = new jwtsecuritytokenhandler().writetoken(token) });
        }

4.基于角色的授权

        [httpget]
        [authorize(roles ="test")]
        public actionresult<string> authvalue()
        {
            var name = user.findfirst(claimtypes.name)?.value;
            var role = user.findfirst(claimtypes.role)?.value;
            _logger.loginformation($"权限登录,用户名:{name},角色:{role}");

            return $"权限登录,用户名:{name},角色:{role}";
        }
roles角色如果有多个,可以以逗号隔开。

5.基于策略的授权

//startup.cs中添加策略
services.addauthorization(options => { options.addpolicy("onlytestaccess", policy => policy.requireclaim("test", new string[] { "test1", "test2" })); options.addpolicy("departmentaccess", policy => policy.requireclaim("department")); });
        // 方法上增加策略    
[httpget] [authorize(policy = "onlytestaccess")] public actionresult<string> authextensionvalue() { var name = user.findfirst(claimtypes.name)?.value; var role = user.findfirst(claimtypes.role)?.value; _logger.loginformation($"基于策略的登录,用户名:{name},角色:{role}"); return $"基于策略的登录,用户名:{name},角色:{role}"; }

6.运行的截图

.NET Core的JWT认证的学习

.NET Core的JWT认证的学习


7.github上的源码

https://github.com/jasonhua95/samll-project/tree/master/jwtapidemo