0

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

问题是这些:

  1. 如何在用户登录应用程序之前保持 JWT 令牌有效,而无需再次询问他/她的登录凭据以向他/她提供另一个有效的 JWT 令牌?
  2. 用户决定退出应用后,如何使 JWT 令牌失效?
4

2 回答 2

0
 // 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);
    }

--

于 2020-02-02T13:30:26.130 回答
0

如何在用户登录应用程序之前保持 JWT 令牌有效,而无需再次询问他/她的登录凭据以向他/她提供另一个有效的 JWT 令牌?

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

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

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

更新:

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

文档: “exp”(过期时间)声明标识了 JWT 不得被接受处理的过期时间或之后。“exp”声明的处理要求当前日期/时间必须在“exp”声明中列出的到期日期/时间之前。

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

于 2018-08-15T11:28:53.337 回答