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

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

程序员文章站 2022-10-06 08:42:05
上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分。比如我们有许多接口。有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问;以保证重要数据不会泄露。 关于JWT *上是这样定义的: JWT(读作 [/dʒɒt/]),即JSON Web To ......

上接:.netcore webapi——swagger简单配置

 

任何项目都有权限这一关键部分。比如我们有许多接口。有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问;以保证重要数据不会泄露。

 

关于jwt

*上是这样定义的:

jwt(读作 [/dʒɒt/]),即json web tokens,是一种基于json的、用于在网络上声明某种主张的令牌(token)。jwt通常由三部分组成: 头信息(header), 消息体(payload)和签名(signature)。它是一种用于双方之间传递安全信息的表述性声明规范。jwt作为一个开放的标准(rfc 7519),定义了一种简洁的、自包含的方法,从而使通信双方实现以json对象的形式安全的传递信息。

 

认证的工作流程:

1. 客户端携带用户名、密码向授权服务申请 "令牌(token)"

2.授权服务器验证用户名、密码后根据它的身份生成一张专属的 "令牌" 并jwt的格式规范返回给客户端

3.客户端将获取到的令牌放入到http的请求头中,然后向资源服务器发起请求。服务器根据客户端发送过来的令牌来进行下一步处理(根据身份来响应客户端是否具有当前接口的权限)

如下图所示:

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 正文:

主要参考园友  在7楼  的这篇文章 https://www.cnblogs.com/raywang/p/9536524.html 

 1. 启用swagger的验证功能

在startup类中新添加红色部分代码。启动项目观察效果。

// 注册swagger服务
            services.addswaggergen(c =>
            {
                // 添加文档信息
                c.swaggerdoc("v1", new info
                {
                    title = "corewebapi",
                    version = "v1",
                    description = "asp.net core webapi",
                    contact = new contact
                    {
                        name = "jee",
                        email = "xiaomaprincess@gmail.com",
                        url = "https://www.cnblogs.com/jixiaosa/"
                    }
                });

                #region 读取xml信息

                // 使用反射获取xml文件。并构造出文件的路径
                var xmlfile = $"{assembly.getexecutingassembly().getname().name}.xml";
                var xmlpath = path.combine(appcontext.basedirectory, xmlfile);
                // 启用xml注释. 该方法第二个参数启用控制器的注释,默认为false.
                c.includexmlcomments(xmlpath, true);
                #endregion

                #region 启用swagger验证功能
                //添加一个必须的全局安全信息,和addsecuritydefinition方法指定的方案名称一致即可,coreapi。
                var security = new dictionary<string, ienumerable<string>> { { "coreapi", new string[] { } }, };
                c.addsecurityrequirement(security);
                c.addsecuritydefinition("coreapi", new apikeyscheme
                {
                    description = "jwt授权(数据将在请求头中进行传输) 在下方输入bearer {token} 即可,注意两者之间有空格",
                    name = "authorization",//jwt默认的参数名称
                    in = "header",//jwt默认存放authorization信息的位置(请求头中)
                    type = "apikey"
                });
                #endregion

            });

 

没启动swagger验证之前是这样的:

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

 

启用验证之后再看:多了个小按钮

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

 

 

点开之后是如下界面:文本框里要如输入从服务器获取的token。格式为:bearer + 空格+token。 bearer可以看作是一个默认的规则。

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

2.生成token

.net core 内置了许多帮助类,巧妙的使用这些类组合,就可以生成我们想要的 token

新建一个tokenl类,编写一个方法来获取jwt字符串

 /// <summary>
    /// 生成jwt字符串
    /// </summary>
    public class token
    {
        // 密钥,注意不能太短
        public static string secretkey { get; set; } = "xiaomaprincess@gmail.com";
        /// <summary>
        /// 生成jwt字符串
        /// </summary>
        /// <param name="tokenmodel"></param>
        /// <returns></returns>
        public static string getjwt(tokenmodel tokenmodel)
        {
            //datetime utc = datetime.utcnow;
            var claims = new list<claim>
            {
                new claim(jwtregisteredclaimnames.jti,tokenmodel.id.tostring()),
                // 令牌颁发时间
                new claim(jwtregisteredclaimnames.iat, $"{new datetimeoffset(datetime.now).tounixtimeseconds()}"),
                new claim(jwtregisteredclaimnames.nbf,$"{new datetimeoffset(datetime.now).tounixtimeseconds()}"),
                 // 过期时间 100秒
                new claim(jwtregisteredclaimnames.exp,$"{new datetimeoffset(datetime.now.addseconds(100)).tounixtimeseconds()}"),
                new claim(jwtregisteredclaimnames.iss,"api"), // 签发者
                new claim(jwtregisteredclaimnames.aud,"user") // 接收者
            };

            
            // 密钥
            var key = new symmetricsecuritykey(encoding.utf8.getbytes(secretkey));
            var creds = new signingcredentials(key, securityalgorithms.hmacsha256);

            var tokenhandler = new jwtsecuritytokenhandler();

            jwtsecuritytoken jwt = new jwtsecuritytoken(
                
                claims: claims,// 声明的集合
                //expires: .addseconds(36), // token的有效时间
                signingcredentials: creds
                );
            var handler = new jwtsecuritytokenhandler();
            // 生成 jwt字符串
            var strjwt = handler.writetoken(jwt);
            return strjwt;
        }
}

 

基本信息类

 public class tokenmodel
    {
        /// <summary>
        /// id
        /// </summary>
        public int id { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 手机
        /// </summary>
        public string phone { get; set; }
        /// <summary>
        /// 邮箱
        /// </summary>
        public string email { get; set; }
        /// <summary>
        /// 身份
        /// </summary>
        public string sub { get; set; }
    }

 

添加一个方法来获取token

/// <summary>
        /// 获取令牌
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="name">账号</param>
        /// <returns></returns>
        [httppost]
        public string getjwt(int id,string name)
        {
            tokenmodel tokenmodel = new tokenmodel
            {
                id = id,
                name=name
            };

            return token.getjwt(tokenmodel);
        }

 

在startup类中配置身份认证服务

(1)在configureservices方法中注册服务

 #region 添加验证服务

            // 添加验证服务
            services.addauthentication(x =>
            {
                x.defaultauthenticatescheme = jwtbearerdefaults.authenticationscheme;
                x.defaultchallengescheme = jwtbearerdefaults.authenticationscheme;
            }).addjwtbearer(o =>
            {
                o.tokenvalidationparameters = new tokenvalidationparameters
                {
                    // 是否开启签名认证
                    validateissuersigningkey = true,
                    issuersigningkey = new symmetricsecuritykey(encoding.ascii.getbytes(token.secretkey)),
                    // 发行人验证,这里要和token类中claim类型的发行人保持一致
                    validateissuer = true,
                    validissuer = "api",//发行人
                    // 接收人验证
                    validateaudience = true,
                    validaudience = "user",//订阅人
                    validatelifetime = true,
                    clockskew = timespan.zero,
                };
            });
            #endregion

(2)在configure方法中启用验证中间件

   // 启用swagger中间件
            app.useswagger();
            // 配置swaggerui
            app.useswaggerui(c =>
            {
                c.swaggerendpoint("/swagger/v1/swagger.json", "coreapi");
                c.routeprefix = string.empty;
            });
            // 启用认证中间件
            app.useauthentication();
            app.usemvc();

 

3. 添加一个测试测控制器来检测是否成功

注意要添加 [authorize]标签

 

  /// <summary>
    /// 需要身份认证的控制器
    /// </summary>
    [route("api/[controller]/[action]")]
    [produces("application/json")]
    [apicontroller]
    [authorize]// 添加授权特性
    public class testcontroller : controllerbase
    {
        /// <summary>
        /// 认证通过之后可访问
        /// </summary>
        /// <returns></returns>
        [httppost]
        public actionresult<tokenmodel> get(tokenmodel tokenmodel)
        {
            return new tokenmodel{ id=1 };
        }

    }

 

启动项目

测试一: 在没有获取token时访问此方法

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

 返回401 身份验证未通过理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

测试二:先访问getjwt接口获取token,在访问test接口

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

最后将获取的token输入到swagger的文本框中:bearer +空格+token

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

 再次访问test接口:成功返回数据

理解ASP.NET Core验证模型(Claim, ClaimsIdentity, ClaimsPrincipal)不得不读的英文博文

 

至此,一个简单身份认证加授权就完成了。

推荐一篇大神的文章 :讲述claim的

理解asp.net core验证模型(claim, claimsidentity, claimsprincipal)不得不读的英文博文