#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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS