配置jwt

jwt 官网地址:JSON Web Tokens - jwt.io

学习jwt就要先学习 http协议 session cookie 

一、

  1. HTTP 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录;

  2. Session 和 Cookie 的主要目的就是为了弥补 HTTP 的无状态特性。

二、

  1. 什么是Session

    客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session 对象,存储结构ConcurrentHashMap。Session 弥补了 HTTP 无状态特性,服务器可以利用 Session 存储客户端在同一个会话期间的一些操作记录。

  2. Session 缺点

Session 机制有个缺点,比如 A 服务器存储了 Session,就是做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。

三、

  1. 什么是Cookies

HTTP 协议中的 Cookie 包括 Web Cookie 和浏览器 Cookie,它是服务器发送到 Web 浏览器的一小块数据。服务器发送到浏览器的 Cookie,浏览器会进行存储,并与下一个请求一起发送到服务器。通常,它用于判断两个请求是否来自于同一个浏览器,例如用户保持登录状态。

HTTP Cookie 机制是 HTTP 协议无状态的一种补充和改良

  1. Cookies 主要三目的

  2. Cookie 主要用于下面三个目的

    会话管理 登陆、购物车、游戏得分或者服务器应该记住的其他内容

    个性化 用户偏好、主题或者其他设置

    追踪 记录和分析用户行为

    Cookie 曾经用于一般的客户端存储。虽然这是合法的,因为它们是在客户端上存储数据的唯一方法,但如今建议使用现代存储 API。Cookie 随每个请求一起发送,因此它们可能会降低性能(尤其是对于移动数据连接而言。

  3. 如果 Cookie 不包含到期日期,则将其视为会话 Cookie.会话 Cookie 存储在内存中,永远不会写入磁盘,当浏览器关闭时,此后 Cookie 将永久丢失

  4. 如果 Cookie 包含有效期 ,则将其视为持久性 Cookie。在到期指定的日期,Cookie 将从磁盘中删除。

四、

  1. JSON Web Token (JWT) 是一个开放标准 ( RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间以 JSON 对象的形式安全传输信息。此信息可以验证和信任,因为它是数字签名的。JWT 可以使用密钥(使用HMAC算法)或使用**RSAECDSA**的公钥/私钥对进行签名。

    虽然 JWT 可以加密以在各方之间提供保密性,但我们将专注于签名令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌会向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是签署它的一方。

  2. 什么时候使用 以下是 JSON Web 令牌有用的一些场景:

    • 授权:这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且能够在不同的域中轻松使用。

    • 信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。因为可以对 JWT 进行签名(例如,使用公钥/私钥对),所以您可以确定发件人就是他们所说的那个人。此外,由于使用标头和有效负载计算签名,您还可以验证内容没有被篡改。

  3. JSON Web Token 结构是什么?在其紧凑的形式中,JSON Web Tokens 由以点 ( .) 分隔的三部分组成,它们是:

    • 标题

    • 有效载荷

    • 签名

    因此,JWT 通常如下所示。

  4. xxxxx.yyyyy.zzzzz

五、

在.net 5.0里加jwt 

1.在GuGet包里下载

Microsoft.AspNetCore.Authentication.Jwt

 

 2.在使用的层创建JWTHelper文件夹 里面添加类

 

 这个类的代码如下:

 public IConfiguration Configuration { get; }
        public JwtToken(IConfiguration configuration)
        {
            this.Configuration = configuration;
        }
        /// <summary>
        /// 生产令牌
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="expireMinutes">过期时间</param>
        /// <returns></returns>
        public string GenerateToken(string userName,int expireMinutes=30)
        {
            //获取发生人
            var issuer = Configuration.GetSection("JwtSettings:Issuer").Value;
            //获取的是密钥
            var signKey = Configuration.GetSection("JwtSettings:SignKey").Value;

            var claims = new List<Claim>();
            //添加主题
            claims.Add(new Claim(JwtRegisteredClaimNames.Sub, issuer));
            claims.Add(new Claim(JwtRegisteredClaimNames.Jti, userName));

            //添加角色信息
            claims.Add(new Claim("Role", "User"));
            claims.Add(new Claim("Role", "Admin"));

            var userClaimsIdentity = new ClaimsIdentity(claims);
            //根据signKey 得到加密之后的key
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signKey));
            //加密方式
            var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

            // 建立 SecurityTokenDescriptor
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = issuer,
                //Audience = issuer, // 由於你的 API 受眾通常沒有區分特別對象,因此通常不太需要設定,也不太需要驗證
                //NotBefore = DateTime.Now, // 預設值就是 DateTime.Now
                //IssuedAt = DateTime.Now, // 預設值就是 DateTime.Now
                Subject = userClaimsIdentity,
                Expires = DateTime.Now.AddMinutes(expireMinutes),
                SigningCredentials = signingCredentials
            };

            // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
            var tokenHandler = new JwtSecurityTokenHandler();
            var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            var serializeToken = tokenHandler.WriteToken(securityToken);

            return serializeToken;


        }

3.在appsettings.json中添加jwt的签名部分

  "JwtSettings": {
    "Issuer": "JwtAuthDemo",
    "SignKey": "ABCDEFOSAODIOJGOIEJF2902SJDFOISDJGOIJOIJ" //长度大于16个字符以上的字符串 ,秘钥
  }

4.在startup.cs的ConfigureServices方法的AddSwaggerGen里加如下代码:

 #region 开启Swagger认证
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {

                    Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[] { }
                    }
                });
                #endregion

4.在startup.cs加验证

//验证
            services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                // 當驗證失敗時,回應標頭會包含 WWW-Authenticate 標頭,這裡會顯示失敗的詳細錯誤原因
                options.IncludeErrorDetails = true; // 預設值為 true,有時會特別關閉

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // 透過這項宣告,就可以從 "sub" 取值並設定給 User.Identity.Name
                    NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
                    // 透過這項宣告,就可以從 "roles" 取值,並可讓 [Authorize] 判斷角色
                    RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",

                    // 一般我們都會驗證 Issuer
                    ValidateIssuer = true,
                    ValidIssuer = Configuration.GetValue<string>("JwtSettings:Issuer"),

                    // 通常不太需要驗證 Audience
                    ValidateAudience = false,
                    //ValidAudience = "JwtAuthDemo", // 不驗證就不需要填寫

                    // 一般我們都會驗證 Token 的有效期間
                    ValidateLifetime = true,

                    // 如果 Token 中包含 key 才需要驗證,一般都只有簽章而已
                    ValidateIssuerSigningKey = false,

                    // "1234567890123456" 應該從 IConfiguration 取得
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue<string>("JwtSettings:SignKey")))
                };
            });

5.加入验证之后在Startup.cs里的Configure方法的授权上面加入鉴权:app.UseAuthentication();

 

 

 

 6.在控制器的上方加上过滤器就好了:[Authorize]

 

 

下面是允许匿名访问的代码

 

posted @ 2022-05-27 20:33  王启贤  阅读(370)  评论(0)    收藏  举报