ruby-jwt (Ruby)Ruby
错误信息
Not enough or too many segments
也可能输出为
- Not enough or too many segments (JWT::DecodeError)
- Invalid base64 encoding (JWT::Base64DecodeError)
ruby-jwt 2.x 抛出的是带有相同文本的 `JWT::DecodeError`。带 `Bearer` 前缀的情况报出的是“Invalid base64 encoding (JWT::Base64DecodeError)”。
ruby-jwt (Ruby) — JWT::DecodeError (JWT::MalformedTokenError in 3.x) from JWT.decode
含义
ruby-jwt 按点号拆分输入,没有找到签名 JWT 应有的三段,因此没有再做其他检查。在 ruby-jwt 3.x 中,异常类为 `JWT::MalformedTokenError`(它是 `JWT::TokenError` 的子类,而后者又是 `JWT::DecodeError` 的子类),因此现有的 `rescue JWT::DecodeError` 代码块仍能捕获它。如果令牌还带着 `Bearer ` 前缀,它确实能拆分成三段,但会在第一段上失败,报出的是另一个错误“Invalid base64 encoding”。
原因
空值或非 JWT 的值
常见被 `to_s` 转成 `""` 的缺失请求头、会话 Cookie,或者从来就不是 JWT 的不透明 OAuth 访问令牌。
整个 Authorization 请求头都被拿去解码
常见`request.headers["Authorization"]` 返回的是 `Bearer eyJ…`。解码前先去掉方案前缀。
加密的令牌
罕见`JWT.decode` 不支持由五段组成的 JWE 令牌;必须先用 JWE 库解密。
修复方法
- 1.
先提取令牌并检查其格式
在令牌交给 ruby-jwt 之前,只接受 `Bearer <header.payload.signature>` 形式的值,其他一律返回 401。
ruby def bearer_token(request) scheme, token = request.authorization.to_s.split(" ", 2) return nil unless scheme&.casecmp?("Bearer") && token&.count(".") == 2 token end token = bearer_token(request) or return head(:unauthorized) payload, _header = JWT.decode(token, public_key, true, algorithm: "ES256")