编写自己的asp.net Jwt身份认证

本文详细介绍了JWT的身份认证原理,包括jwttoken的格式、生成过程,以及如何在ASP.NET中使用SecurityTokenDescriptor。还讨论了如何将JWT传递到服务器并进行身份验证,以及API访问权限的设置方法。
摘要由CSDN通过智能技术生成

jwt身份认证的原理

jwt token的格式

jwt token 的格式为 Header.Payload.VeritySignature.
实际jwt如下

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

用Json格式表示如下:

"jwt":{
	"header":{
				"alg": "HS256",
  				"typ": "JWT"
			}
	"payload":{
				"sub": "1234567890",
  				"name": "John Doe",
  				"iat": 1516239022
			}
	"VerifySignature":
			{
				HMACSHA256(base64UrlEncode(header) + "." +
						  base64UrlEncode(payload),  
						your-256-bit-secret).toBase64String()
			}
}

生成jwt

作为使用者,自己需要掌握SecurityTokenDescriptor类的参数,通过调用JsonWebTokenHandler().CreateToken(new SecurityTokenDescriptor() ) 来生成jwt。asp.net SecurityTokenDescriptor 的构造函数如下:

public class SecurityTokenDescriptor
{
    //
    // 摘要:
    //     Gets or sets the value of the 'audience' claim.
    public string Audience { get; set; }
    //
    // 摘要:
    //     Defines the compression algorithm that will be used to compress the JWT token
    //     payload.
    public string CompressionAlgorithm { get; set; }
    //
    // 摘要:
    //     Gets or sets the Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.EncryptingCredentials
    //     used to create a encrypted security token.
    public EncryptingCredentials EncryptingCredentials { get; set; }
    //
    // 摘要:
    //     Gets or sets the value of the 'expiration' claim. This value should be in UTC.
    public DateTime? Expires { get; set; }
    //
    // 摘要:
    //     Gets or sets the issuer of this Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.
    public string Issuer { get; set; }
    //
    // 摘要:
    //     Gets or sets the time the security token was issued. This value should be in
    //     UTC.
    public DateTime? IssuedAt { get; set; }
    //
    // 摘要:
    //     Gets or sets the notbefore time for the security token. This value should be
    //     in UTC.
    public DateTime? NotBefore { get; set; }
    //
    // 摘要:
    //     Gets or sets the token type. If provided, this will be added as the value for
    //     the 'typ' header parameter. In the case of a JWE, this will be added to both
    //     the inner (JWS) and the outer token (JWE) header. By default, the value used
    //     is 'JWT'. If Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.AdditionalHeaderClaims
    //     also contains 'typ' header claim value, it will override the TokenType provided
    //     here. This value is used only for JWT tokens and not for SAML/SAML2 tokens
    public string TokenType { get; set; }

    //
    // 摘要:
    //     Gets or sets the System.Collections.Generic.Dictionary`2 which represents the
    //     claims that will be used when creating a security token. If both and Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.Subject
    //     are set, the claim values in Subject will be combined with the values in Claims.
    //     The values found in Claims take precedence over those found in Subject, so any
    //     duplicate values will be overridden.
    public IDictionary<string, object> Claims { get; set; }
    //
    // 摘要:
    //     Gets or sets the System.Collections.Generic.Dictionary`2 which contains any custom
    //     header claims that need to be added to the JWT token header. The 'alg', 'kid',
    //     'x5t', 'enc', and 'zip' claims are added by default based on the Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.SigningCredentials,
    //     Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.EncryptingCredentials,
    //     and/or Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.CompressionAlgorithm
    //     provided and SHOULD NOT be included in this dictionary as this will result in
    //     an exception being thrown. These claims are only added to the outer header (in
    //     case of a JWE).
    public IDictionary<string, object> AdditionalHeaderClaims { get; set; }
    //
    // 摘要:
    //     Gets or sets the System.Collections.Generic.Dictionary`2 which contains any custom
    //     header claims that need to be added to the inner JWT token header. The 'alg',
    //     'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.SigningCredentials,
    //     Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.EncryptingCredentials,
    //     and/or Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.CompressionAlgorithm
    //     provided and SHOULD NOT be included in this dictionary as this will result in
    //     an exception being thrown. For JsonWebTokenHandler, these claims are merged with
    //     Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.AdditionalHeaderClaims
    //     while adding to the inner JWT header.
    public IDictionary<string, object> AdditionalInnerHeaderClaims { get; set; }
    //
    // 摘要:
    //     Gets or sets the Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.SigningCredentials
    //     used to create a security token.
    public SigningCredentials SigningCredentials { get; set; }
    //
    // 摘要:
    //     Gets or sets the System.Security.Claims.ClaimsIdentity. If both and Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor.Subject
    //     are set, the claim values in Subject will be combined with the values in Claims.
    //     The values found in Claims take precedence over those found in Subject, so any
    //     duplicate values will be overridden.
    public ClaimsIdentity Subject { get; set; }
}

生成Jwt的实际代码:

public string CreatJwt(IdentityUser user,int AddMinutes)
{
    PasswordHasher<IdentityUser> hasher = new PasswordHasher<IdentityUser>();
    RSA rSA = RSA.Create();
   string s= _config.GetValue<string>("RSAPrivateKey");
    byte[] b=System.Convert.FromBase64String(s);
    int i;
    rSA.ImportRSAPrivateKey(b, out i);
    var okey = new RsaSecurityKey(rSA);
    IdentityUser user0 = _Dbcontext.Users.FirstOrDefault(o => o.Id == user.Id);
    if (user != null)
    {
        string? jwt = new JsonWebTokenHandler().CreateToken(new SecurityTokenDescriptor()
        {
            Issuer = "NewSoft",
            Audience = "lxl",
            IssuedAt = DateTime.UtcNow,
            NotBefore = DateTime.UtcNow,
            Expires = DateTime.UtcNow.AddMinutes(AddMinutes),
            Subject = new System.Security.Claims.ClaimsIdentity(new List<Claim>
            {
                new Claim("email", user.Email),
                new Claim("host", "192.168.3.2"),
                new Claim(ClaimTypes.Name,user.UserName),
                new Claim(ClaimTypes.Role,"asd"),
               
            }, "myBearer"),
            SigningCredentials = new SigningCredentials(okey, SecurityAlgorithms.RsaSha384Signature)
        }); ;
        return jwt;
    }
    else
        return "";
}

使用Jwt

把Jwt 传递到服务器

1.使用变量传递到服务器

代码如下:

MessageRecieveContext ctx
if (ctx.Request.Query.ContainsKey("token"))
{
    ctx.Token = ctx.Request.Query["token"];
}

2.使用Cookies

代码如下:

if (!string.IsNullOrEmpty(ctx.HttpContext.Request.Cookies["token"]))
{
    ctx.Token= ctx.HttpContext.Request.Cookies["token"];
}

服务器身份认证

服务器收到HttpContext.Request后,调用Authentication服务,自动进行身份的认证与授权。

builder.Services.AddAuthentication(o => o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme).AddJwtBearer("Bearer",o=>
{
    RSA rsa = RSA.Create();
   string s = builder.Configuration.GetValue<string>("RSAPublicKey");
    byte[] b = new byte[2048];
    int i = 0;
    b=System.Convert.FromBase64String(s);
    rsa.ImportRSAPublicKey(b, out i);    
    o.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidIssuer = "NewSoft",
        ValidateAudience = true,
        ValidAudience = "lxl",
        IssuerSigningKey = new RsaSecurityKey(rsa),
        ValidateIssuerSigningKey = true
    }; 
} 

上例代码,当服务器收到httpContext后,用RSA公钥,对jwt进行验证签名,若签名无误,则将身份信息写入HttpContext.User.Identity中,再根据用户名,角色等,授予request的访问权限。

Api访问权限的设置

Api的访问权限设置时,只需要在Api函数前加上[Authorize(Roles ="admin,asd")],即代表允许角色为admin 和asd的进行访问。当然,你也可以设定用户名为:“张三,李四,王麻子”的调用权限。你不特殊设定,只要通过认证的任何人和任何角色都可访问。

 [Authorize(Roles ="admin,asd")]
 // GET: Stations
 public async Task<IActionResult> Index()
 {
     return View(await _context.Stationss.ToListAsync());
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值