赞
踩
Spring Security
提供了对 OAuth2
的支持,该包下提供 4
个模块:
oauth2-core
,基础核心模块oauth2-jose
,JOSE:Javascript Object Signing and Encryption
,对应 JWS
JWE
的实现oauth2-client
,oauth2 client
组件的实现oauth2-resource-server
,oauth2 resource server
组件的实现本文是基于 oauth2-jose
模块的一些 demo
展示,对应依赖 spring-securty-oauth2-jose
Nimbus
应该是目前最好用的 JWT API
了,spring-security-oauth2-jose
也是基于 Nimbus API
的封装
@Test public void rs256() throws JOSEException, ParseException, InterruptedException { // 生成 REA256 密钥对 RSAKey rsaKey = new RSAKeyGenerator(2048) .generate(); RSAKey publicJWK = rsaKey.toPublicJWK(); String publicJWKJson = publicJWK.toJSONString(); // JWT 加签 JWSSigner signer = new RSASSASigner(rsaKey); /** * JWTClaimsSet:JWT 携带信息的封装,有一些既定的属性比如 * issuer * subject * ... */ JWTClaimsSet jwtClaimsSet = new JWTClaimsSet.Builder() .expirationTime(new Date(new Date().getTime() + 5 * 1000)) .audience("xsn") .build(); SignedJWT signedJWT = new SignedJWT( new JWSHeader(JWSAlgorithm.RS256) , jwtClaimsSet ); signedJWT.sign(signer); String jwt = signedJWT.serialize(); // TimeUnit.SECONDS.sleep(6); // 用公钥验签 JWT SignedJWT parse = SignedJWT.parse(jwt); JWSVerifier verifier = new RSASSAVerifier( RSAKey.parse(publicJWKJson) ); boolean verify = parse.verify(verifier); if (verify) { System.out.println(parse.getJWTClaimsSet().getAudience()); } }
RSA256
应该是最常用的 JWS
算法,一般地:认证中心基于该算法加签,客户端则基于对应的 公钥
验签Nimbus
提供开箱即用的 API
生成 RSAKey
JWTClaimsSet Builder API
轻松的构造 JWT
的信息,它还定义了一些默认的属性比如 issuer
subject
expireTime
等demo
包含基于 RSA256
的 加签
和 验签
@Test public void hs256() throws JOSEException, ParseException { // HS256 对称密钥加密 SecureRandom random = new SecureRandom(); byte[] bytes = new byte[32]; random.nextBytes(bytes); JWSSigner signer = new MACSigner(bytes); JWSObject jwt = new JWSObject( new JWSHeader(JWSAlgorithm.HS256) , new Payload("hello jwt") ); jwt.sign(signer); String serialize = jwt.serialize(); JWSObject parse = JWSObject.parse(serialize); JWSVerifier verifier = new MACVerifier(bytes); boolean verify = parse.verify(verifier); if (verify) { System.out.println(parse.getPayload()); } }
HS256
RSA256
类似@Test public void jwkMatcher() throws JOSEException { // JWK: Json Web Key JWK jwk1 = new RSAKey.Builder(new RSAKeyGenerator(2048).generate()) .keyID("id1") .keyOperations(new HashSet<KeyOperation>() {{ add(KeyOperation.SIGN); }}) .build(); JWK jwk2 = new RSAKey.Builder(new RSAKeyGenerator(2048).generate()) .keyID("id1") .keyOperations(new HashSet<KeyOperation>() {{ add(KeyOperation.ENCRYPT); }}) .build(); JWK jwk3 = new RSAKey.Builder(new RSAKeyGenerator(2048).generate()) .keyID("id3") .keyOperations(new HashSet<KeyOperation>() {{ add(KeyOperation.ENCRYPT); }}) .build(); // JWK 集合 JWKSet jwkSet = new JWKSet(new ArrayList<JWK>() {{ add(jwk1); add(jwk2); add(jwk3); }}); /** * JWKMatcher 可以基于 keyId keyOperation JWT Head * 等属性从 JWKSet 中匹配对应的 JWK */ JWKMatcher matcher1 = new JWKMatcher.Builder() .keyID("id1") .build(); JWKMatcher matcher2 = new JWKMatcher.Builder() .keyOperations(KeyOperation.SIGN) .build(); List<JWK> select1 = new JWKSelector(matcher1).select(jwkSet); List<JWK> select2 = new JWKSelector(matcher2).select(jwkSet); select1.forEach(System.out::println); System.out.println("----"); select2.forEach(System.out::println); }
JWK
,Json Web Key
,比如 RSAKey
JWKSet
,JWK
的集合封装JWKMatcher
则是基于 keyID
keyOperation
等属性从 JWKSet
中匹配对应的 JWK
集合spring-security-oauth2-jose
底层依赖 Nimbus
,主要封装了两个大的 API
:
JwtEncoder
,负责对 JWT
编码(JWS
或 JWE
)JwtDecoder
,负责 JWT
的解码@Test public void rs256() throws JOSEException, InterruptedException { // JwtEncoder:spring security jose 基于 Nimbus 的 JWT 加密类 RSAKey rsaKey = new RSAKeyGenerator(2048).generate(); JwtEncoder encoder = new NimbusJwtEncoder( new ImmutableJWKSet<>( new JWKSet(rsaKey) ) ); Jwt jwt = encoder.encode(JwtEncoderParameters.from( JwsHeader.with(SignatureAlgorithm.RS256) // .jwk(new HashMap<>() {{ put("publicKey", rsaKey.toPublicKey()); }}) .build() , JwtClaimsSet.builder() .expiresAt(Instant.now().plusSeconds(5)) .subject("xsn") .claim("content", "hello spring jwt") .build() ) ); String tokenValue = jwt.getTokenValue(); // TimeUnit.SECONDS.sleep(6); // DefaultJWTProcessor 自带对 JWT 过期的校验 DefaultJWTProcessor<SecurityContext> processor = new DefaultJWTProcessor<>(); processor.setJWSKeySelector(new JWSVerificationKeySelector<SecurityContext>( JWSAlgorithm.RS256 , new ImmutableJWKSet<>(new JWKSet(rsaKey.toPublicJWK())) )); JwtDecoder decoder = new NimbusJwtDecoder(processor); Jwt decode = decoder.decode(tokenValue); System.out.println(decode.getClaim(JwtClaimNames.SUB).toString()); System.out.println(decode.getClaim("content").toString()); }
RSA256
算法的 加签
验签
过程DefaultJWTProcessor
包含对 JWT
过期时间的校验,对应 JwtClaimNames
的 expireTime
属性,比如示例中的 JWT
有效期为 5s
这些 API
一般可能不会直接使用,是 Spring Security
对 OAuth2 JWT
的核心支持
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。