简体   繁体   English

.net 核心 2.0 JWT 令牌

[英].net core 2.0 JWT token

I have a web Api built with .net core 2.0 and a mobile app built with xamarin.我有一个使用 .net core 2.0 构建的 web Api 和一个使用 xamarin 构建的移动应用程序。 To login the mobile app make a call to the web api by passing (username and password).要登录移动应用程序,请通过传递(用户名和密码)调用 web api。 If the credentials are valid web Api provide back a JWT token.如果凭据是有效的 Web Api,则提供回 JWT 令牌。 The mobile app has a feature that keep the user logged in even when you close the app, like (facebook, Instagram etc...).移动应用程序有一项功能,即使您关闭应用程序,也可以让用户保持登录状态,例如(Facebook、Instagram 等...)。

The question are these:问题是这些:

  1. How to keep the JWT token valid until the user is logged-In in the app without ask him/her again the login credentials to give him/her another valid JWT token?如何在用户登录应用程序之前保持 JWT 令牌有效,而无需再次询问他/她的登录凭据以向他/她提供另一个有效的 JWT 令牌?
  2. How to make the JWT token invalid after the user decide to logout from the app?用户决定退出应用后,如何使 JWT 令牌无效?

How to keep the JWT token valid until the user is logged-In in the app without ask him/her again the login credentials to give him/her another valid JWT token?如何在用户登录应用程序之前保持 JWT 令牌有效,而无需再次询问他/她的登录凭据以向他/她提供另一个有效的 JWT 令牌?

You can set a token expiry date and keep track of that.您可以设置令牌到期日期并跟踪该日期。

How to make the JWT token invalid after the user decide to logout from the app?用户决定退出应用后,如何使 JWT 令牌无效?

  • If you keep the expiry time short and keep refreshing the token expiry until the user logs out.如果您保持较短的到期时间并不断刷新令牌到期,直到用户注销。
  • You can save some kind of blacklist of invalid tokens so you can validate against that.您可以保存某种无效令牌的黑名单,以便您可以对其进行验证。

Update:更新:

The JWT consists of the Header, Payload and Signature. JWT 由 Header、Payload 和 Signature 组成。 You can read all about it here In the payload you can set an claim called: "exp".您可以在此处阅读所有相关信息 在有效负载中,您可以设置一个名为“exp”的声明。

The docs: The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.文档: “exp”(过期时间)声明标识了 JWT 不得被接受处理的过期时间或之后的过期时间。 The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim. “exp”声明的处理要求当前日期/时间必须在“exp”声明中列出的到期日期/时间之前。

Also, while researching to clarify my answer I found this SO answer: JSON Web Token expiration .另外,在研究澄清我的答案时,我发现了这个答案: JSON Web Token expire

 // This code tested with dotnet core 2.1 ( WebApi + Jwt )  with sample structure 

//Add One class Auth to your project //添加一个类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;
    }
}

Models I have used:我用过的模型:

 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; }
}

In Startup.cs在 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);
    }

-- ——

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM