JWT
ClownFish内置了 JWT 的实现, 可用来生成或者解析 JWT-TOKEN
生成 JWT-TOKEN
var data = new {
iss = "JwtUtilsTest",
sub = "all",
iat = DateTime.Now.ToNumber(),
exp = DateTime.Now.AddDays(1).ToNumber(),
UseId = 123,
UserName = "Fish Li",
UserRole = "Admin"
};
string json = data.ToJson();
string token = JwtUtils.Encode(json, JwtKey, "HS512");
或者
WebUserInfo user = new WebUserInfo {
UserCode = "code111",
UserName = "name123",
UserId = "id_111",
UserRole = "admin",
TenantId = "tid_2222",
TenantCode = "tcode_333",
UserType = "type111"
};
int expirationSeconds = 3600 * 24; // token 有效期 24 小时
string token = AuthenticationManager.GetLoginToken(user, expirationSeconds)
解析 JWT-TOKEN
绝大多数情况下,业务代码不需要 解析JWT-TOKEN,因为这个步骤属于 身份认证 的范畴,框架会自动处理。
有2类场景下可能会需要:
- MessageHandler
- BackgroundTask
此时可以参考以下示例:
string token = ...............; // 假设你已获取一个 jwt-token
string payload = JwtUtils.Decode(token, secretKey, algorithmName);
示例代码中的 payload 通常是一个 json 字符串,后面你只需要根据实现情况做反序列化即可。
说明:
- 如果参数 secretKey=null,那么将忽略签名验证
- Decode不做有效期检查,需要自行实现。原因:有效性的定义没有形成标准,ClownFish没法做!
- 框架自带的AuthenticateModule会始终执行 签名和有效期 验证。
支持的算法
JwtUtils工具类支持以下这些算法:
- HS256
- HS512
- RS256
- RS512
- ES256
- ES512
注意:后面4个是 非对称 算法,需要使用另外2个不同的方法
public static class JwtUtils
{
public static string Encode2(string payload, X509Certificate2 x509, string algorithmName);
public static string Decode2(string token, X509Certificate2 x509, string algorithmName);
}
注意事项&不推荐做法
JWT-TOKEN应该由服务端生成,永远不要让客户端生成TOKEN
有些项目中会把 签名密钥和算法名 交给调用方,由调用方来生成 JWT-TOKEN,这是一种 非常愚蠢的设计!!
这种做法有2个危害:
- 不安全。因为 签名密钥 泄露了,调用方可以生成各种权限的TOKEN,服务端根本没法限制或者校验。
- 数据结构没法升级。TOKEN中通常会包含一个数据结构(可参考前面示例),假设一开始 Token数据结构包含3个成员,和调用方约定后,人家按你的定义去实现了,你再想加其它成员就非常难了。
(还有更离谱的真实案例)一开始的3个成员的赋值格式也可能不统一,典型的是 “有效期”这种时间格式,PHPer可能会给赋值一个数字~~ ,而你期望的是一个 DateTime