首页 > 编程知识 正文

spring源码深度解析,io.jsonwebtoken.jjwt

时间:2023-05-04 22:45:48 阅读:179629 作者:4221

jwt源代码分析author:zxw

email:502513206@qq.com

@ Jishou University

1 .前言最近在做jwt许可证服务。 这意味着为请求的用户生成token。 但是,关于token的验证并不是由我的服务负责,而是由网关统一处理。 jwt以前也用过几次,但我不太熟悉,只知道它是用base64Url算法加密的。 因为这次正好用了,所以看看jjwt的实现吧。

2 .将jjwt包导入源代码分析java后,可以使用包提供的Builder为jwt生成token。 以下是基本用法。

jtbuilderbuilder=jwts.builder (.setheader ) /头部信息. setid )/id:jwt的唯一标识符. set//Subject ) subject /Issuer :发行者. 从名称中可以看出,它是使用builder结构模式生成的,缺省情况下返回DefaultJwtBuilder对象

JwtBuilder

publicstaticjwtbuilderbuilder ((returnnewdefaultjwtbuilder ) ); }我们知道}defaultjwtbuilderjwt由header、payload、Signature三部分组成。

publicclassdefaultjwtbuilderimplementsjwtbuilder { privatestaticfinalobjectmapperobject _ mapper=new object mapper (; 私有标题; //Header private Claims claims; 私有字符串支付; //运营商privatesignaturealgorithmalgorithm; //签名算法私有密钥; private byte[] keyBytes; 私有压缩编码解码器; //压缩算法(} Header头部由类型和加密算法这两个信息构成,具体类型如下。

{ 'typ': 'JWT ',' alg ' : ' hs 256 ' }头在jjwt上有表示头部的头界面,可以看到头的固定键

publicinterfaceheadertextendsheadertextendsmapstring、 Object { /** JWT {@code Type} (typ ) value : code ' jwt '/code/* * jwt { @ codetype } header parameter name : code/* * jwt { @ code content type } header parameter name : code ' cty '/code */publicstaticfinalstringcontent _ type=' cty header parameter name : code ' zip '/code */publicstaticfinalstringcompression _ }/* * jjwtlegacy/deprecatedcompressionalgorithmheaderparametername : code ' calg '/code * @ deprecated use { @ link # comment instead.*/@

PRESSION_ALGORITHM = "calg";}

DefaultHeaderjjwt中默认会使用该类,当然我们也能自己实现Header接口或者继承该类实现自定义的Header,可以看到Header其实就是一个Map,我们也能往头部添加我们自定义的数据

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

接下来就是第二部分载体了,在jjwt中我们可以传入json的payload载体也可以用claim封装我们的载体,二者只能选一个。

Claims可以看到cliams同样是个map,我们在使用setSubject等方法时,实际上就是往下面的key设置对应的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"}所对应的值

public JwtBuilder signWith(SignatureAlgorithm alg, Key key) { Assert.notNull(alg, "SignatureAlgorithm cannot be null."); Assert.notNull(key, "Key argument cannot be null."); // 加密算法,默认使用HS256 this.algorithm = alg; // secret,我们与客户端规定的密钥 this.key = key; return this; } @Override public 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."); }// 如果为空,生成默认的Header Header header = ensureHeader(); Key key = this.key; // 如果未指定密钥算法,则生成默认的算法 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); }// 设置头部的alg对应的算法类型 if (key != null) { jwsHeader.setAlgorithm(algorithm.getValue()); } else { //no signature - plaintext JWT: jwsHeader.setAlgorithm(SignatureAlgorithm.NONE.getValue()); }// 设置压缩算法 if (compressionCodec != null) { jwsHeader.setCompressionAlgorithm(compressionCodec.getAlgorithmName()); }// 头部进行base64Url加密 String base64UrlEncodedHeader = base64UrlEncode(jwsHeader, "Unable to serialize header to json."); String base64UrlEncodedBody;// 对载体进行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;// 对签名进行base64Url加密 if (key != null) { //jwt must be signed:// 生成Signer,下发给客户端的密钥 JwtSigner signer = createSigner(algorithm, key);// 对前两部分进行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.1 jwt += JwtParser.SEPARATOR_CHAR; }// 返回token return jwt; }

可以看到jwt的组成,对header进行base64Url加密 + payload的base64Url加密 + (header + payload + secret)三部分加密组成。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。