JWT單點(diǎn)登錄源碼學(xué)習(xí)

      網(wǎng)友投稿 710 2022-05-30

      你好我是辰兮,很高興你能來(lái)閱讀,本篇給是初學(xué)JWT單點(diǎn)登錄后的困惑,現(xiàn)在源碼學(xué)習(xí)后更加了解JWT的結(jié)構(gòu),小結(jié)下來(lái),獻(xiàn)給初學(xué)者,共同成長(zhǎng),一起進(jìn)步。

      JWT單點(diǎn)登錄案例:JWT單點(diǎn)登錄代碼實(shí)現(xiàn)

      文章目錄

      一、JWT的結(jié)構(gòu)

      二、JWT源碼學(xué)習(xí)

      三、JWT 的特點(diǎn)小結(jié)

      一、JWT的結(jié)構(gòu)

      JWT的結(jié)構(gòu)是什么樣的?

      token構(gòu)成包含三個(gè)部分:

      Header 頭部

      Payload 負(fù)載

      Signature 簽名

      //格式如下 xxx.yyy.zzz

      1

      2

      ①JWT-header(頭信息)

      由兩部分組成,令牌類(lèi)型(即:JWT)、散列算法(HMAC、RSASSA、RSASSA-PSS等)

      JWT頭部分是一個(gè)描述JWT元數(shù)據(jù)的JSON對(duì)象,通常如下所示。

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

      1

      2

      3

      4

      然后,這個(gè)JSON被編碼為Base64Url,形成JWT的第一部分。

      ②有效載荷payload

      有效載荷部分,是JWT的主體內(nèi)容部分,也是一個(gè)JSON對(duì)象,包含需要傳遞的數(shù)據(jù)。

      JWT的第二部分是payload,其中包含claims。

      claims是關(guān)于實(shí)體(常用的是用戶信息)和其他數(shù)據(jù)的聲明

      claims有三種類(lèi)型: registered, public, and private claims。

      Registered claims: 這些是一組預(yù)定義的claims,非強(qiáng)制性的,但是推薦使用, iss(發(fā)行人), exp(到期時(shí)間),sub(主題), aud(觀眾)等;

      Public claims: 自定義claims,注意不要和JWT注冊(cè)表中屬性沖突,這里可以查看JWT注冊(cè)表;

      Private claims:這些是自定義的claims,用于在同意使用這些claims的各方之間共享信息,它們既不是Registered claims,也不是Public claims;

      { "sub": "1234567890", "name": "Tom", "admin": true }

      1

      2

      3

      4

      5

      6

      請(qǐng)注意,默認(rèn)情況下JWT是未加密的,任何人都可以解讀其內(nèi)容,因此不要構(gòu)建隱私信息字段,存放保密信息,以防止信息泄露。

      JSON對(duì)象也使用Base64 URL算法轉(zhuǎn)換為字符串保存。

      ③簽名哈希

      簽名哈希部分是對(duì)上面兩部分?jǐn)?shù)據(jù)簽名,通過(guò)指定的算法生成哈希,以確保數(shù)據(jù)不會(huì)被篡改。

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

      1

      2

      3

      4

      eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SfcKxwRJSMeKF2QT4fwpMeJf36POkayJV_adQssw6f

      1

      2

      3

      4

      在計(jì)算出簽名哈希后,JWT頭,有效載荷和簽名哈希的三個(gè)部分組合成一個(gè)字符串,每個(gè)部分用"."分隔,就構(gòu)成整個(gè)JWT對(duì)象。

      ④Base64URL算法

      如前所述,JWT頭和有效載荷序列化的算法都用到了Base64URL。該算法和常見(jiàn)Base64算法類(lèi)似,稍有差別。

      作為令牌的JWT可以放在URL中

      (例如api.example/?token=xxx)

      。 Base64中用的三個(gè)字符是"+","/“和”=",由于在URL中有特殊含義,因此Base64URL中對(duì)他們做了替換:"=“去掉,”+“用”-“替換,”/“用”_"替換,這就是Base64URL算法。

      二、JWT源碼學(xué)習(xí)

      參考一下常見(jiàn)的代碼初學(xué)者可能看上去很復(fù)雜,接下來(lái)分析一波

      //登錄成功之后,需要生成token String token = Jwts.builder().setSubject("用戶名/用戶信息") //主題,可以放用戶的詳細(xì)信息 .setIssuedAt(new Date()) //token創(chuàng)建時(shí)間 .setExpiration(new Date(System.currentTimeMillis() + 60000)) //token過(guò)期時(shí)間 .setId("用戶ID") //用戶ID .setClaims(hashMap) //配置角色信息 .signWith(SignatureAlgorithm.HS256, "WuHan") //加密方式和加密密碼 .compact();

      1

      2

      3

      4

      5

      6

      7

      8

      首先Jwts是Java已經(jīng)被人寫(xiě)好的一個(gè)被final修飾的類(lèi),然后里面自帶很多方法

      // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package io.jsonwebtoken; import io.jsonwebtoken.impl.DefaultClaims; import io.jsonwebtoken.impl.DefaultHeader; import io.jsonwebtoken.impl.DefaultJwsHeader; import io.jsonwebtoken.impl.DefaultJwtBuilder; import io.jsonwebtoken.impl.DefaultJwtParser; import java.util.Map; public final class Jwts { private Jwts() { } public static Header header() { return new DefaultHeader(); } public static Header header(Map header) { return new DefaultHeader(header); } public static JwsHeader jwsHeader() { return new DefaultJwsHeader(); } public static JwsHeader jwsHeader(Map header) { return new DefaultJwsHeader(header); } public static Claims claims() { return new DefaultClaims(); } public static Claims claims(Map claims) { return new DefaultClaims(claims); } public static JwtParser parser() { return new DefaultJwtParser(); } public static JwtBuilder builder() { return new DefaultJwtBuilder(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      JwtBuilder是一個(gè)接口,里面也自帶很多方法,每一個(gè)方法的返回值類(lèi)型是自己本身,這里就是給用戶設(shè)置相關(guān)信息的,所以代碼你看上去是連著set的。

      // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package io.jsonwebtoken; import java.security.Key; import java.util.Date; import java.util.Map; public interface JwtBuilder extends ClaimsMutator { JwtBuilder setHeader(Header var1); JwtBuilder setHeader(Map var1); JwtBuilder setHeaderParams(Map var1); JwtBuilder setHeaderParam(String var1, Object var2); JwtBuilder setPayload(String var1); JwtBuilder setClaims(Claims var1); JwtBuilder setClaims(Map var1); JwtBuilder addClaims(Map var1); JwtBuilder setIssuer(String var1); JwtBuilder setSubject(String var1); JwtBuilder setAudience(String var1); JwtBuilder setExpiration(Date var1); JwtBuilder setNotBefore(Date var1); JwtBuilder setIssuedAt(Date var1); JwtBuilder setId(String var1); JwtBuilder claim(String var1, Object var2); JwtBuilder signWith(SignatureAlgorithm var1, byte[] var2); JwtBuilder signWith(SignatureAlgorithm var1, String var2); JwtBuilder signWith(SignatureAlgorithm var1, Key var2); JwtBuilder compressWith(CompressionCodec var1); String compact(); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      JWT的解析

      try { JwtParser parser = Jwts.parser(); parser.setSigningKey("WuHan");//解析 要和上面“暗號(hào)”一樣 Jws claimsJws = parser.parseClaimsJws(token); Claims body = claimsJws.getBody(); String username = body.getSubject(); // Object role = body.get("role"); return true; } catch (ExpiredJwtException e) { e.printStackTrace(); } catch (UnsupportedJwtException e) { e.printStackTrace(); } catch (MalformedJwtException e) { e.printStackTrace(); } catch (SignatureException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      setSigningKey() 與builder中簽名方法signWith()對(duì)應(yīng),parser中的此方法擁有與signWith()方法相同的三種參數(shù)形式,用于設(shè)置JWT的簽名key,用戶后面對(duì)JWT進(jìn)行解析。

      package io.jsonwebtoken; import java.security.Key; import java.util.Date; public interface JwtParser { char SEPARATOR_CHAR = '.'; JwtParser requireId(String var1); JwtParser requireSubject(String var1); JwtParser requireAudience(String var1); JwtParser requireIssuer(String var1); JwtParser requireIssuedAt(Date var1); JwtParser requireExpiration(Date var1); JwtParser requireNotBefore(Date var1); JwtParser require(String var1, Object var2); JwtParser setClock(Clock var1); JwtParser setAllowedClockSkewSeconds(long var1); JwtParser setSigningKey(byte[] var1); JwtParser setSigningKey(String var1); JwtParser setSigningKey(Key var1); JwtParser setSigningKeyResolver(SigningKeyResolver var1); JwtParser setCompressionCodecResolver(CompressionCodecResolver var1); boolean isSigned(String var1); Jwt parse(String var1) throws ExpiredJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; T parse(String var1, JwtHandler var2) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; Jwt parsePlaintextJwt(String var1) throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; Jwt parseClaimsJwt(String var1) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; Jws parsePlaintextJws(String var1) throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; Jws parseClaimsJws(String var1) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      Claims認(rèn)證很難解釋清楚,甚至我都找不到一個(gè)合適的中文詞語(yǔ)來(lái)翻譯它。只好用一個(gè)比喻來(lái)說(shuō)明。

      在實(shí)行社保卡之前,我們?nèi)メt(yī)院看病的時(shí)候,需要拿著身份證去辦理一張就診卡,辦卡的工作人員校驗(yàn)完你的身份證以后,會(huì)將你的個(gè)人信息錄入到卡里面。當(dāng)你去找醫(yī)生就診的時(shí)候,醫(yī)生掃描一下你的就診卡,就知道了你的所有信息。這個(gè)就診卡就相當(dāng)于Claims認(rèn)證中的token,里面的每條信息就是一個(gè)Claim.

      package io.jsonwebtoken; import java.util.Date; import java.util.Map; public interface Claims extends Map, ClaimsMutator { String ISSUER = "iss"; String SUBJECT = "sub"; String AUDIENCE = "aud"; String EXPIRATION = "exp"; String NOT_BEFORE = "nbf"; String ISSUED_AT = "iat"; String ID = "jti"; String getIssuer(); Claims setIssuer(String var1); String getSubject(); Claims setSubject(String var1); String getAudience(); Claims setAudience(String var1); Date getExpiration(); Claims setExpiration(Date var1); Date getNotBefore(); Claims setNotBefore(Date var1); Date getIssuedAt(); Claims setIssuedAt(Date var1); String getId(); Claims setId(String var1); T get(String var1, Class var2); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      上述Claims接口中定義了一些變量,我找到了相關(guān)圖片給你們參考

      iss (issuer):簽發(fā)人 exp (expiration time):過(guò)期時(shí)間 sub (subject):主題 aud (audience):受眾 nbf (Not Before):生效時(shí)間 iat (Issued At):簽發(fā)時(shí)間 jti (JWT ID):編號(hào)

      1

      2

      3

      4

      5

      6

      7

      三、JWT 的特點(diǎn)小結(jié)

      (1)JWT 默認(rèn)是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。

      (2)JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫(xiě)入 JWT。

      (3)JWT 不僅可以用于認(rèn)證,也可以用于交換信息。有效使用 JWT,可以降低服務(wù)器查詢(xún)數(shù)據(jù)庫(kù)的次數(shù)。

      (4)JWT 的最大缺點(diǎn)是,由于服務(wù)器不保存 session 狀態(tài),因此無(wú)法在使用過(guò)程中廢止某個(gè) token,或者更改 token 的權(quán)限。也就是說(shuō),一旦 JWT 簽發(fā)了,在到期之前就會(huì)始終有效,除非服務(wù)器部署額外的邏輯。

      (5)JWT 本身包含了認(rèn)證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT 的有效期應(yīng)該設(shè)置得比較短。對(duì)于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證。

      JWT單點(diǎn)登錄(源碼學(xué)習(xí))

      (6)為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸。

      The best investment is to invest in yourself

      2020.06.04 記錄辰兮的第76篇博客

      JSON

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Docker核心技術(shù)之容器詳解
      下一篇:Excel數(shù)據(jù)分析功能使用教程
      相關(guān)文章
      久久亚洲国产成人亚| 亚洲精品国产成人| 亚洲人片在线观看天堂无码| 亚洲av日韩av高潮潮喷无码| 国产亚洲精品无码拍拍拍色欲| 久久精品国产亚洲AV| 亚洲a视频在线观看| 亚洲人成电影在线天堂| 亚洲色爱图小说专区| 亚洲线精品一区二区三区| 亚洲中文字幕无码一去台湾 | 国产成人亚洲综合a∨| 亚洲综合色区中文字幕| 色噜噜亚洲男人的天堂| 亚洲婷婷第一狠人综合精品| 亚洲人色大成年网站在线观看| 亚洲免费黄色网址| 一区二区亚洲精品精华液 | 亚洲视频在线观看2018| 亚洲国产成a人v在线观看| 亚洲永久在线观看| 亚洲av中文无码乱人伦在线观看| 亚洲精品V天堂中文字幕| 豆国产96在线|亚洲| 亚洲日本在线观看视频| 亚洲中文无韩国r级电影| 亚洲理论电影在线观看| 亚洲人成影院在线| 亚洲伊人久久精品| 亚洲精品无码人妻无码| 国产亚洲漂亮白嫩美女在线| 国产精品亚洲色婷婷99久久精品| 亚洲Aⅴ无码一区二区二三区软件 亚洲AⅤ视频一区二区三区 | 亚洲精品无码不卡在线播放| 国产成人久久精品亚洲小说| 2022中文字字幕久亚洲| 亚洲AV无码一区二区乱孑伦AS| 亚洲视频免费一区| 亚洲色偷偷色噜噜狠狠99| 久久久久久亚洲精品无码| 国产亚洲情侣一区二区无|