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

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

问题是:

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

【问题讨论】:

    标签: c# .net-core jwt .net-core-2.0 jwt-auth


    【解决方案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

      【讨论】:

      • 通过说“您可以设置令牌到期日期并跟踪该日期。”你的意思是刷新令牌?
      猜你喜欢
      • 2018-10-07
      • 2018-03-30
      • 2021-06-27
      • 2018-01-22
      • 2018-12-21
      • 2017-04-21
      • 2020-07-02
      • 2019-12-22
      • 2018-07-18
      相关资源
      最近更新 更多