设为首页 加入收藏

TOP

Akka-CQRS(15)- Http标准安全解决方案:OAuth2+JWT(一)
2019-08-15 00:10:43 】 浏览:139
Tags:Akka-CQRS Http 标准 安全 解决方案 OAuth2 JWT

  上期讨论过OAuth2, 是一种身份认证+资源授权使用模式。通过身份认证后发放授权凭证。用户凭授权凭证调用资源。这个凭证就是一种令牌,基本上是一段没什么意义的加密文,或者理解成密钥也可以。服务方通过这个令牌来获取用户身份信息,也就是说服务端必须维护一个已经获得身份验证的用户信息清单。研究了一下JWT,发现它本身可以携带加密后的一些信息包括用户信息,而这些信息又可以通过同样的加密算法解密恢复。也就是说服务端是可以直接对收到的JWT解密恢复用户信息,这样用起来就方便多了。还记着我们的POS例子里客户端必须构建一个指令,如:http://www.pos.com/logIn?shopid=1001&userid=234 这个Uri里的shopid是明码的,会造成很大安全风险。使用JWT后,我们可以把shopid,单号什么的都放在JWT里就安全多了。

先了解一下JWT:JWT也是一个行业标准:RFC7519,是一个用Json格式传递加密信息的方式。JWT的结构如下:

header.payload.signiture 如:hhhhh.ppppp.ssssss

header:由两部分组成:1、令牌类型,在这里是JWT, 2、签名算法如 HMAC SHA256 or RSA, 下面是个header例子:

{ "alg": "HS256", "typ": "JWT" }

payload:可以用来承载用户自定义信息,如userid, shopid, vchnum ...

{
  "shopid": "1101",
  "userid": "102",
  "vchnum": 12
}

signiture: 就是把 加密后的header+加密后的payload+secret 用header提供的签名算法签名,如下:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

我的目标是把一些用来辨识用户、权限以及状态信息加密存在JWT内发送给用户,用户在请求中提交他的JWT,服务端再解密并取出内部信息然后确定如何处理用户请求。

JWT本身原理并不复杂,应用场景也不是很多,所以不想花太多精力研究它。刚好,找到一个开源的scala JWT工具库jwt-scala. 下面就利用项目源代码来了解一下JWT的操作,包括:加密、解密、验证、获取payload内部claims值。

JWT encode 方法如下:

  /** Encode a JSON Web Token from its different parts. Both the header and the claim will be encoded to Base64 url-safe, then a signature will be eventually generated from it if you did pass a key and an algorithm, and finally, those three parts will be merged as a single string, using dots as separator.
    *
    * @return $token
    * @param header $headerString
    * @param claim $claimString
    * @param key $key
    * @param algorithm $algo
    */
  def encode(header: String, claim: String, key: String, algorithm: JwtAlgorithm): String = {
    val data = JwtBase64.encodeString(header) + "." + JwtBase64.encodeString(claim)
    data + "." + JwtBase64.encodeString(JwtUtils.sign(data, key, algorithm))
  }

所以产生JWT的元素都在参数里了。我们可以直接用payload.claims来构建JWT:

 /** An alias to `encode` which will provide an automatically generated header.
    *
    * @return $token
    * @param claim $claimString
    */
  def encode(claim: String): String = encode(JwtHeader().toJson, claim)

  /** An alias to `encode` which will provide an automatically generated header and setting both key and algorithm
    * to None.
    *
    * @return $token
    * @param claim the claim of the JSON Web Token
    */
  def encode(claim: JwtClaim): String = encode(claim.toJson)

 def encode(header: String, claim: String): String = {
    JwtBase64.encodeString(header) + "." + JwtBase64.encodeString(claim) + "."
  }

这样看一个正确的JWT可以没有签名那部分的:hhhhh.ppppp。想想还是要用签名,安全点。用下面这个函数就可以了:

  /** An alias to `encode` which will provide an automatically generated header and allowing you to get rid of Option
    * for the key and the algorithm.
    *
    * @return $token
    * @param claim $claimString
    * @param key $key
    * @param algorithm $algo
    */
  def encode(claim: String, key: String, algorithm: JwtAlgorithm): String =
    encode(JwtHeader(algorithm).toJson, claim, key, algorithm)

/** Deserialize an algorithm from its string equivalent. Only real algorithms supported,
    * if you need to support "none", use "optionFromString".
    *
    * @return the actual instance of the algorithm
    * @param algo the name of the algorithm (e.g.
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Spark家族:Win10系统下搭建Scala.. 下一篇Akka-CQRS(14)- Http标准安全解..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目