.net core 2.0 JWT 令牌

Posted

技术标签:

【中文标题】.net core 2.0 JWT 令牌【英文标题】:.net core 2.0 JWT token 【发布时间】:2019-01-21 00:02:16 【问题描述】:

我有一个使用 .net core 2.0 构建的 Web Api 和一个使用 xamarin 构建的移动应用程序。要登录移动应用程序,请通过传递(用户名和密码)调用 web api。如果凭证是有效的 Web Api,则返回一个 JWT 令牌。该移动应用程序具有一项功能,即使您关闭应用程序(例如(facebook、Instagram 等)),用户也可以保持登录状态。

问题是:

    如何在用户登录之前保持 JWT 令牌有效 应用程序无需再次询问他/她的登录凭据以给他/她 另一个有效的 JWT 令牌? 用户决定注销后如何让JWT令牌失效 来自应用程序?

【问题讨论】:

【参考方案1】:
 // This code tested with dotnet core 2.1 ( WebApi + Jwt )  with sample structure 

//为你的项目添加一个类Auth

public static class Auth

    private static string salt = "jnyanendra_sethi"; // u can chose any key satisfying the length 
    private static int timeoutInMinute = 1;
    private static string _issuer = "http://localhost:5000";
    private static string _audience = "http://localhost:5000";

    //Generate Token
    public static string GenerateToken(Customer customer, List<SupplierInfo> lstSpplierInfo)
    
        var securitykey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
        var credential = new SigningCredentials(securitykey, SecurityAlgorithms.HmacSha256);

        // var suppliers = any json string e.g. ["SupplierId":1001,"SupplierName":"RateHawk","SupplierId":1002,"SupplierName":"Hotelbeds"]
        var suppliers = JsonConvert.SerializeObject(lstSpplierInfo);//"ur json object to store in claim";
        var claims = new List<Claim> 
           new Claim("CustomerName", customer.CustomerName),
           new Claim("Suppliers",suppliers )
       ;

        var mytoken = new JwtSecurityToken(issuer: _issuer, audience: _audience,
            claims: claims, notBefore: DateTime.Now, expires: DateTime.Now.AddMinutes(timeoutInMinute), signingCredentials: credential);
        var tokenValue = new JwtSecurityTokenHandler().WriteToken(mytoken);
        return tokenValue;
    

    //Validate token

    public static void ValidateJwtToken(this IServiceCollection services)
    
        var securitykey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
        var credential = new SigningCredentials(securitykey, SecurityAlgorithms.HmacSha256);

        var tokenParam = new TokenValidationParameters
        
            ValidateIssuerSigningKey = true,
            ValidIssuer = _issuer,
            ValidAudience = _audience,
            ValidateIssuer = true,
            ValidateAudience = true,
            RequireSignedTokens = true,
            IssuerSigningKey = credential.Key,
            ClockSkew = TimeSpan.FromMinutes(timeoutInMinute)
        ;

        services.AddAuthentication(
            options =>
            
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            )
            .AddJwtBearer(
            options =>
            
                options.TokenValidationParameters = tokenParam;
            );

    


[Route("api/[controller]")]
[ApiController]
public class HotelController : ControllerBase


    [HttpGet("Search")]
    public SearchReponse Search()// u can take search parameters for input
    
        // based on apikey or username, call db for first time
        // get customername / supplierinfo from db
        Customer customer = new Customer()  CustomerId = "CUS001", CustomerName = "TestCust" ;// dummy
        if (customer == null)
        
            this.HttpContext.Response.StatusCode = 401;
            return new SearchReponse()
            
                ErrorInfo = new ErrorInfo()
                
                    Code = "0",
                    Description = "No Customer Found"
                
            ;
        

        string token = Auth.GenerateToken(customer, GetDummyDataToStoreInClaim());

        SearchReponse reponse = new SearchReponse()
        
            GeneralInfo = new GeneralInfo()
            
                Token = token,
                Duration = 0
            ,
            Hotels = "Hotels Data",
        ;
        return reponse;
    

    [Authorize]
    [HttpGet("Get/id")]
    public ActionResult<string> Get(int id)
    //// Getting the data stored in claim that required for further process
        var CustomerName = HttpContext.User.Identities.FirstOrDefault().Claims.FirstOrDefault(x => x.Type == "CustomerName").Value;
        var strSuppliers = HttpContext.User.Identities.FirstOrDefault().Claims.FirstOrDefault(x => x.Type == "Suppliers").Value;
        return CustomerName;
    


我用过的型号:

 public class SearchReponse

    public GeneralInfo GeneralInfo  get; set; 
    public ErrorInfo ErrorInfo  get; set; 
    public string Hotels  get; set; 

public class GeneralInfo

    public string Token  get; set; 
    public long Duration  get; set; 

public class ErrorInfo

    public string Code  get; set; 
    public string Description  get; set; 


在 Startup.cs 中

public void ConfigureServices(IServiceCollection services)
    

        services.ValidateJwtToken();
        services.AddAuthorization(Options => 
            Options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
        );
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    

--

【讨论】:

【参考方案2】:

如何在用户登录应用程序之前保持 JWT 令牌有效 无需再次询问他/她的登录凭据即可给他/她 另一个有效的 JWT 令牌?

您可以设置令牌到期日期并对其进行跟踪。

用户决定退出应用后,如何让 JWT 令牌失效?

如果您缩短到期时间并不断刷新令牌到期,直到用户注销。 您可以保存某种无效令牌的黑名单,以便进行验证。

更新:

JWT 由 Header、Payload 和 Signature 组成。您可以阅读有关它的所有内容here 在有效负载中,您可以设置一个名为:“exp”的声明。

The docs: “exp”(过期时间)声明标识过期时间 或者在此之后,JWT 不得被接受处理。这 处理“exp”声明需要当前日期/时间 必须早于“exp”声明中列出的到期日期/时间。

另外,在研究澄清我的答案时,我发现了这个 SO 答案:JSON Web Token expiration。

【讨论】:

通过说“您可以设置令牌到期日期并跟踪该日期。”你的意思是刷新令牌?

以上是关于.net core 2.0 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

.net core 2.0 JWT 令牌过期问题

具有用户权限的基于 JWT 令牌的授权 Asp.net core 2.0

ASP.NET Core 2.0 JWT 验证失败并出现“用户授权失败:(null)”错误

ASP.NET Core 中的 Jwt 令牌身份验证

使用外部 JWT 令牌 ASP.NET CORE

.Net Core API JWT 令牌验证