c# - .net core 2.0 JWT 令牌
问题描述
我有一个使用 .net core 2.0 构建的 Web Api 和一个使用 xamarin 构建的移动应用程序。要登录移动应用程序,请通过传递(用户名和密码)调用 web api。如果凭证是有效的 Web Api,则返回一个 JWT 令牌。该移动应用程序具有一项功能,即使您关闭应用程序(例如(facebook、Instagram 等)),用户也可以保持登录状态。
问题是这些:
- 如何在用户登录应用程序之前保持 JWT 令牌有效,而无需再次询问他/她的登录凭据以向他/她提供另一个有效的 JWT 令牌?
- 用户决定退出应用后,如何使 JWT 令牌失效?
解决方案
// 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);
}
--
推荐阅读
- python - 在 Python 中迭代列表中的连续元素,以便最后一个元素与第一个元素结合
- qt - 可以将 QtQuick 标签的 CSS 空白设置为预包装吗?
- sql-server - org.hibernate.HibernateException:无法确定类的类型:com.microsoft.sqlserver.jdbc.SQLServerDataTable
- python - 如何计算 Django 中页面的访问量?(通过重定向)
- oop - 我如何使许多不同的结构都实现了相同的特征,并且可以相互比较?
- python - sqlalchemy 创建没有命名关键字的插入对象
- vba - 访问模块中的事件命令按钮事件处理程序
- c++ - 改善 OCR 结果
- c++ - 是否有像 ADTF2 那样的结构化属性?
- ios - 使用相同的请求标识符同时注册 2 个本地通知不被覆盖