#author("2023-11-16T17:55:55+08:00","default:Admin","Admin") #author("2024-01-24T22:48:30+08:00","default:Admin","Admin") [[ASP.NET Core Web]] &color(red){※This article is based on .NET 7}; #contents * 概要 [#kd0a4304] ** 什么是JWT [#k677d8a4] JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。 JWT的官网地址: https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT令牌在api接口中校验用户的身份以确认用户是否有访问api的权限。 JWT中包含了身份认证必须的参数以及用户自定义的参数,JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。 ** JSON Web令牌应用场景 [#n7673376] 授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,允许用户访问该令牌允许的路由,服务和资源。Single Sign On是一种现在广泛使用JWT的功能,因为它的开销很小,并且能够在不同的域中轻松使用。 信息交换:JSON Web令牌是在各方之间安全传输信息的好方法。因为JWT可以签名 - 例如,使用公钥/私钥对 - 您可以确定发件人是他们所说的人。此外,由于使用标头和有效负载计算签名,您还可以验证内容是否未被篡改。 ** JWT令牌结构 [#y9140a0d] 在紧凑的形式中,JSON Web Tokens由dot(.)分隔的三个部分组成,它们是: - Header 头 - Payload 有效载荷 - Signature 签名 JWT通常如下所示: xxxxx.yyyyy.zzzzz *** Header 头 [#n3426f42] 标头通常由两部分组成:令牌的类型,即JWT,以及正在使用的签名算法,例如HMAC SHA256或RSA。 例如: #codeprettify{{ { "alg": "HS256", "typ": "JWT" } }} 然后,这个JSON被编码为Base64Url,形成JWT的第一部分。 *** Payload 有效载荷 [#k7ead102] Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。 #codeprettify{{ iss (issuer):签发人 exp (expiration time):过期时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号 }} 除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。例如: #codeprettify{{ { "sub": "1234567890", "name": "John Doe", "admin": true } }} 注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。这个 JSON 对象也要使用 Base64URL 算法转成字符串。 *** Signature 签名 [#ad092971] Signature 部分是对前两部分的签名,防止数据篡改。 首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。 #codeprettify{{ HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) }} 签名用于验证消息在此过程中未被更改,并且,在使用私钥签名的令牌的情况下,它还可以验证JWT的发件人是否是它所声称的人。 可以使用下面的 Debugger 来解码,验证和生成JWT https://jwt.io/ &ref(netcore_jwt1.jpg); * JWT的读取和写入 [#db2b9ee3] ** 写入 [#kccc6d3a] #codeprettify{{ var claims = new Claim[] { new Claim(ClaimTypes.Name, "user01"), new Claim(ClaimTypes.Role, "ROLE_NORMAL"), new Claim("UserID", 100), }; //对称秘钥 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("sdfsdfs8fs")); //签名证书(秘钥,加密算法) var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //生成token [注意]需要nuget添加Microsoft.AspNetCore.Authentication.JwtBearer包,并引用System.IdentityModel.Tokens.Jwt命名空间 var token = new JwtSecurityToken("API", "http://localhost:61381", claims, DateTime.Now, DateTime.Now.AddHours(8), creds); string userToken = new JwtSecurityTokenHandler().WriteToken(token); }} ** 读取 [#md4885b0] #codeprettify{{ ClaimsPrincipal principal = HttpContext.Current.User as ClaimsPrincipal; if (null != principal) { foreach (Claim claim in principal.Claims) { Response.Write("CLAIM TYPE: " + claim.Type + "; CLAIM VALUE: " + claim.Value + "</br>"); } } }} #hr(); コメント: #comment_kcaptcha