日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jjwt源码解析

發(fā)布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jjwt源码解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

jjwt源碼解析

author:zxw

email:502513206@qq.com

@ Jishou University


1.前言

最近在做一個jwt授權(quán)服務(wù),其實也就是給請求的用戶生成一個token,不過關(guān)于token的驗證并不在我服務(wù)負(fù)責(zé),而是由網(wǎng)關(guān)去統(tǒng)一處理。jwt之前也用過幾次,不過不是很熟悉只知道是通過base64Url算法進(jìn)行加密,這次剛好用到了所以來看看jjwt的實現(xiàn)。

2.源碼解析

在java中導(dǎo)入jjwt的包就可以使用包中提供的Builder生成jwt的token,以下是基礎(chǔ)的用法。

JwtBuilder builder = Jwts.builder().setHeader(header) // 頭部信息.setId(uuid) //id:是JWT的唯一標(biāo)識.setSubject(subject) //Subject:可以存放用戶信息.setIssuer(appId) //Issuer:簽發(fā)者.setIssuedAt(now) //IssuedAt:jwt的簽發(fā)時間.signWith(signatureAlgorithm, secretKey);

通過名字可以看到,是使用的builder構(gòu)造模式生成,默認(rèn)給我們返回一個DefaultJwtBuilder對象

JwtBuilder

public static JwtBuilder builder() {return new DefaultJwtBuilder();}

DefaultJwtBuilder我們知道jwt是由header,payload,Signature三部分組成。

public class DefaultJwtBuilder implements JwtBuilder {private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();private Header header; // Headerprivate Claims claims;private String payload; // 載體private SignatureAlgorithm algorithm; // 簽名算法private Key key;private byte[] keyBytes;private CompressionCodec compressionCodec; // 壓縮算法 }

Header頭部由兩部分信息組成,一個是類型,一個是加密的算法,具體類型如下。

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

Header在jjwt中有個Header接口表示頭部,可以看到Header的固定key

public interface Header<T extends Header<T>> extends Map<String,Object> {/** JWT {@code Type} (typ) value: <code>"JWT"</code> */public static final String JWT_TYPE = "JWT";/** JWT {@code Type} header parameter name: <code>"typ"</code> */public static final String TYPE = "typ";/** JWT {@code Content Type} header parameter name: <code>"cty"</code> */public static final String CONTENT_TYPE = "cty";/** JWT {@code Compression Algorithm} header parameter name: <code>"zip"</code> */public static final String COMPRESSION_ALGORITHM = "zip";/** JJWT legacy/deprecated compression algorithm header parameter name: <code>"calg"</code>* @deprecated use {@link #COMPRESSION_ALGORITHM} instead. */@Deprecatedpublic static final String DEPRECATED_COMPRESSION_ALGORITHM = "calg"; }

DefaultHeaderjjwt中默認(rèn)會使用該類,當(dāng)然我們也能自己實現(xiàn)Header接口或者繼承該類實現(xiàn)自定義的Header,可以看到Header其實就是一個Map,我們也能往頭部添加我們自定義的數(shù)據(jù)

public class DefaultHeader<T extends Header<T>> extends JwtMap implements Header<T> { }

接下來就是第二部分載體了,在jjwt中我們可以傳入json的payload載體也可以用claim封裝我們的載體,二者只能選一個。

Claims可以看到cliams同樣是個map,我們在使用setSubject等方法時,實際上就是往下面的key設(shè)置對應(yīng)的Value

public interface Claims extends Map<String, Object>, ClaimsMutator<Claims> {/** JWT {@code Issuer} claims parameter name: <code>"iss"</code> */public static final String ISSUER = "iss";/** JWT {@code Subject} claims parameter name: <code>"sub"</code> */public static final String SUBJECT = "sub";/** JWT {@code Audience} claims parameter name: <code>"aud"</code> */public static final String AUDIENCE = "aud";/** JWT {@code Expiration} claims parameter name: <code>"exp"</code> */public static final String EXPIRATION = "exp";/** JWT {@code Not Before} claims parameter name: <code>"nbf"</code> */public static final String NOT_BEFORE = "nbf";/** JWT {@code Issued At} claims parameter name: <code>"iat"</code> */public static final String ISSUED_AT = "iat";/** JWT {@code JWT ID} claims parameter name: <code>"jti"</code> */public static final String ID = "jti"; }

最后一步就是Jwts.builder().signWith(signatureAlgorithm, secretKey);在該方法中指定我們的加密的算法就是頭部{"alg":"HS256"}所對應(yīng)的值

public JwtBuilder signWith(SignatureAlgorithm alg, Key key) {Assert.notNull(alg, "SignatureAlgorithm cannot be null.");Assert.notNull(key, "Key argument cannot be null.");// 加密算法,默認(rèn)使用HS256this.algorithm = alg;// secret,我們與客戶端規(guī)定的密鑰this.key = key;return this;} @Overridepublic String compact() {// 判斷載體是否為空if (payload == null && Collections.isEmpty(claims)) {throw new IllegalStateException("Either 'payload' or 'claims' must be specified.");}// 判斷payload和claim是否都不為空if (payload != null && !Collections.isEmpty(claims)) {throw new IllegalStateException("Both 'payload' and 'claims' cannot both be specified. Choose either one.");}// key和keybytes是否都不為空if (key != null && keyBytes != null) {throw new IllegalStateException("A key object and key bytes cannot both be specified. Choose either one.");}// 如果為空,生成默認(rèn)的HeaderHeader header = ensureHeader();Key key = this.key;// 如果未指定密鑰算法,則生成默認(rèn)的算法if (key == null && !Objects.isEmpty(keyBytes)) {key = new SecretKeySpec(keyBytes, algorithm.getJcaName());}JwsHeader jwsHeader;if (header instanceof JwsHeader) {jwsHeader = (JwsHeader)header;} else {jwsHeader = new DefaultJwsHeader(header);}// 設(shè)置頭部的alg對應(yīng)的算法類型if (key != null) {jwsHeader.setAlgorithm(algorithm.getValue());} else {//no signature - plaintext JWT:jwsHeader.setAlgorithm(SignatureAlgorithm.NONE.getValue());}// 設(shè)置壓縮算法if (compressionCodec != null) {jwsHeader.setCompressionAlgorithm(compressionCodec.getAlgorithmName());}// 頭部進(jìn)行base64Url加密String base64UrlEncodedHeader = base64UrlEncode(jwsHeader, "Unable to serialize header to json.");String base64UrlEncodedBody;// 對載體進(jìn)行base64Url加密if (compressionCodec != null) {byte[] bytes;try {bytes = this.payload != null ? payload.getBytes(Strings.UTF_8) : toJson(claims);} catch (JsonProcessingException e) {throw new IllegalArgumentException("Unable to serialize claims object to json.");}base64UrlEncodedBody = TextCodec.BASE64URL.encode(compressionCodec.compress(bytes));} else {// 加密base64UrlEncodedBody = this.payload != null ?TextCodec.BASE64URL.encode(this.payload) :base64UrlEncode(claims, "Unable to serialize claims object to json.");}String jwt = base64UrlEncodedHeader + JwtParser.SEPARATOR_CHAR + base64UrlEncodedBody;// 對簽名進(jìn)行base64Url加密if (key != null) { //jwt must be signed:// 生成Signer,下發(fā)給客戶端的密鑰JwtSigner signer = createSigner(algorithm, key);// 對前兩部分進(jìn)行base64Url加密String base64UrlSignature = signer.sign(jwt);// 組合jwt += JwtParser.SEPARATOR_CHAR + base64UrlSignature;} else {// no signature (plaintext), but must terminate w/ a period, see// https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25#section-6.1jwt += JwtParser.SEPARATOR_CHAR;}// 返回tokenreturn jwt;}

可以看到j(luò)wt的組成,對header進(jìn)行base64Url加密 + payload的base64Url加密 + (header + payload + secret)三部分加密組成。

總結(jié)

以上是生活随笔為你收集整理的jjwt源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。