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