JWT

概述

  • JWT 基于 token 的鉴权机制,基于 token 的鉴权机制类似于 http 协议也是无状态的,它不需要服务端保留用户认证信息或回话信息,这意味着基于 token 认证机制不需要考虑存在哪台服务器,为应用扩展提供了便利,它的运行流程:

    1. 用户使用用户密码来请求服务器
    2. 服务器进行验证用户信息
    3. 服务器通过验证发送用户一个token
    4. 客户端存储token,并在每次请求时在HTTP头附送上这个token值
    5. 服务端验证token值,并返回数据
  • 通常把JWT Base64编码后保存在HTTP请求头里,这个 token 在每次请求时传给服务端,另外,服务端要支持CORS(跨域访问):Access-Control-Allow-Origin:*

构成

  • 第一部分称它为头部(header),第二部分为载荷(payload),第三部分为签证(signature),将这三部分连接成一个完整字符串就构成了 JWT
    • header
      • jwt 头部承载两部分信息,声明类型,此处为 jwt ,声明加密算法,通常为 HMAC SHA256,完整头部 JSON 如:{'typ':'JWT','alg':'HS256'}
      • 然后进行 base64 加密(可以对称解密),构成第一部分:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
    • payload
      • 载荷是存放有效信息的地方,包括三部分:标签中注册的声明、公共的声明、私有的声明
      • 标准中的注册的声明如:iss(jwt签发者)、sub(jwt所面向用户)、aud(接收jwt的一方)、exp(jwt过期时间)、nbf(定义jwt生效时间)、iat(jwt签发时间)、jti(jwt唯一身份标识,作为一次性token,从而回避重放攻击)
      • 公共的声明:公共的声明可以添加任何信息,一般为用户相关信息或业务信息,但不要加敏感信息,该部分在客户端可解密
      • 私有的声明:私有声明是提供者和消费者所共同定义的声明,不建议存放敏感信息,因为是base64对称加密,该部分信息可以归类为铭文信息
      • 定义一个payload:{"sub":"1234567890","name":"John Doe","admin":true}
      • base64加密得到 JWT 第二部分:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
    • signature
      • 该部分是一个签证信息,由三部分组成:header(base64后)、payload(base64后)、secret(自定义密钥)
      • 由加密后的 header 和 payload 连接组成的字符串,然后通过 header 中声明的加密方式进行 secret 组合加密,构成 JWT 第三部分
    • 注意:secret 是保存在服务端的,JWT 签发生成也是在服务端,secret 就是用来进行 JWT 签发和 JWT 验证的,所以,它是服务端的私钥,任何场景都不能泄漏出去,一旦客户端知道这个 secret 则意味客户端可以自我签发 JWT

总结

优点:
    ■ 因 JSON 通用性,所以 JWT 可跨语言支持
    ■ payload 可存储业务逻辑信息(非敏感性)
    ■ 便于传输,字节占用很小
    ■ 不需要存储在服务端,易于扩展
安全相关:
    ■ 不应该在 JWT 的 payload 存储敏感信息,该部分是可以解密的
    ■ 保护好 secret 私钥,该私钥非常重要
    ■ 如果可以采用 HTTPS 协议   

与 Session 区别

  • Session 通过 cookie 传输,存储在服务器,服务器通过 cookie 中的 sessionID 获取当前会话用户,对于单台服务器没问题,但多服务器就涉及到共享 Session ,而且认证用户多时 Session 会占用大量服务器内存
  • JWT 存储在客户端,服务器不需要存储 JWT ,JWT 里有用户 ID,服务器拿到 JWT 后验证可以获得用户信息,也就实现了 Session 功能,但是是无状态的,只要签名秘钥足够安全就能保证 JWT 可靠性

JWT 为什么能保证信息可靠性?

  • 比如现在有 token :

eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0OTg0ODIxNTQsInN1YiI6InF1ZGluZyIsInVzZXJJZCI6IjEwMzc5NDAxIiwicm9sZSI6ImFkbWluIn0.-YFTYJ6FLlIQqD4G3hYcWvYlYE8H9eAA2369WEcJFVY

{
    "alg": "HS256"
}
{
    "exp": 1498482154,
    "sub": "linyuan",
    "userId": "123456",
    "role": "admin"
}
Sign ��6蒥!ୡaůbV��^땄pU
  • 假设 payload 被劫持了,其他人把 userId 修改为自己的,如 123456 ,但没有签名秘钥,所以没法生成签名,服务端收到该 Token 后,先用 Base64 解码出信息,然后重新生成 Signtrue,使用该 Signtrue 与客户端传来的 Signtrue 对比,一样则证明没被修改,否则拒绝请求

JJWT使用

  1. 通过Maven引入JJWT库:
   <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
</dependency>
  1. 签发 JWT
public static String createJWT() {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
    JwtBuilder builder = Jwts.builder()
            .setId(id)          // JWT_ID
            .setAudience("")    // 接受者
        .setClaims(null)   // 自定义属性
            .setSubject("")     // 主题
        .setIssuer("")     // 签发者
            .setIssuedAt(new Date())    // 签发时间
        .setNotBefore(new Date())  // 失效时间
            .setExpiration(long)      // 过期时间
        .signWith(signatureAlgorithm, secretKey);// 签名算法以及密匙
            return builder.compact();
}
  1. 验证 JWT
public static Claims parseJWT(String jwt) throws Exception {
    SecretKey secretKey = generalKey();
            return Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(jwt)
            .getBody();
}
  1. 当 JWT验证失败时会抛出异常,常见异常有:
    • SignatureException:签名错误异常
    • MalformedJwtException:JWT格式错误异常
    • ExpiredJwtException:JWT过期异常
    • UnsupportedJwtException:不支持的JWT异常
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容