所以我正在開發一個資源服務器(一個 Spring Boot 應用程式),我想利用 Spring Security OAuth2 資源服務器庫的優點。
我現在面臨的問題是授權服務器(另一個 Spring Boot 應用程式)使用對稱密鑰對 JWT 進行簽名,很久以前它被設定為一個非常短的字串,而我無法改變。
我按照 Spring Security 檔案嘗試了這個:
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize -> authorize
.anyRequest().permitAll())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
return NimbusJwtDecoder
.withSecretKey(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HS512"))
.macAlgorithm(MacAlgorithm.HS512)
.build();
}
}
但我收到以下錯誤:
Caused by: com.nimbusds.jose.KeyLengthException: The secret length must be at least 256 bits
at com.nimbusds.jose.crypto.impl.MACProvider.<init>(MACProvider.java:118) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jose.crypto.MACVerifier.<init>(MACVerifier.java:168) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jose.crypto.MACVerifier.<init>(MACVerifier.java:81) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jose.crypto.MACVerifier.<init>(MACVerifier.java:113) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jose.crypto.factories.DefaultJWSVerifierFactory.createJWSVerifier(DefaultJWSVerifierFactory.java:100) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:364) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.createJwt(NimbusJwtDecoder.java:154) ~[spring-security-oauth2-jose-5.5.3.jar:5.5.3]
... 61 common frames omitted
從我所見MACProvider,生成此例外的不可配置且所需的密鑰長度不能放寬。有沒有辦法解決?
謝謝
編輯:
嘗試用 0 填充密鑰的建議,如下所示:
@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
var key = secretKey.getBytes(StandardCharsets.UTF_8);
var paddedKey = Arrays.copyOf(key, 128);
return NimbusJwtDecoder
.withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
.macAlgorithm(MacAlgorithm.HS512)
.build();
}
但現在我收到以下例外:
com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:378) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.createJwt(NimbusJwtDecoder.java:154) ~[spring-security-oauth2-jose-5.5.3.jar:5.5.3]
at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.decode(NimbusJwtDecoder.java:137) ~[spring-security-oauth2-jose-5.5.3.jar:5.5.3]
at org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.getJwt(JwtAuthenticationProvider.java:97) ~[spring-security-oauth2-resource-server-5.5.3.jar:5.5.3]
at org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider.authenticate(JwtAuthenticationProvider.java:88) ~[spring-security-oauth2-resource-server-5.5.3.jar:5.5.3]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.5.3.jar:5.5.3]
at org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter.doFilterInternal(BearerTokenAuthenticationFilter.java:130) ~[spring-security-oauth2-resource-server-5.5.3.jar:5.5.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:178) ~[spring-security-oauth2-client-5.5.3.jar:5.5.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.3.jar:5.5.3]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) ~[spring-boot-actuator-2.5.6.jar:2.5.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.12.jar:5.3.12]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.12.jar:5.3.12]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.54.jar:9.0.54]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
編輯2:
源代碼像這樣生成 JWT(使用 io.jsonwebtoken 0.9.1 庫):
private String generateToken(Map<String, Object> claims, String username) {
Header header = Jwts.header();
header.setType("JWT");
String jti = UUID.randomUUID().toString();
Date now = new Date(System.currentTimeMillis());
return Jwts.builder()
.setClaims(claims)
.setHeader((Map<String, Object>) header)
.setSubject(username)
.setIssuedAt(now)
.setIssuer("issuer")
.setId(jti)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
編輯3:
解決方案:
@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
var key = TextCodec.BASE64.decode(secretKey);
var paddedKey = key.length < 128 ? Arrays.copyOf(key, 128) : key;
return NimbusJwtDecoder
.withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
.macAlgorithm(MacAlgorithm.HS512)
.build();
}
uj5u.com熱心網友回復:
看起來像這樣,HMAC,如果秘密長度比散列演算法的塊大小短,它將用零填充秘密。
并根據這個
塊大小:底層哈希演算法操作的資料塊的大小。對于 SHA-256,這是 512 位,對于 SHA-384 和 SHA-512,這是 1024 位。
輸出長度:底層哈希演算法產生的哈希值的大小。對于 SHA-256,這是 256 位,對于 SHA-384,這是 384 位,對于 SHA-512,這是 512 位。
SHA-512 的塊大小為 128 位元組。
我建議如果源使用 HS512 演算法嘗試用零填充秘密,看看它是否有效。如果您Guava的類路徑中有庫:
Bytes.ensureCapacity(secretKey.getBytes(StandardCharsets.UTF_8), 128, 0);
ensureCapacity 方法源代碼:
public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", padding);
return array.length < minLength ? Arrays.copyOf(array, minLength padding) : array;
}
編輯2:
首先嘗試將秘密解碼為 base 64
byte[] decodedBytes = Base64.decodeBase64(secret)
然后添加填充并在您的解碼器中使用它(如果 的大小decodedBytes小于 128):
Arrays.copyOf(decodedBytes, 128);
我做了以下測驗,一切正常:
private String generateToken(Map<String, Object> claims, String username) {
Header header = Jwts.header();
header.setType("JWT");
String jti = UUID.randomUUID().toString();
Date now = new Date(System.currentTimeMillis());
return Jwts.builder()
.setClaims(claims)
.setHeader((Map<String, Object>) header)
.setSubject(username)
.setIssuedAt(now)
.setIssuer("issuer")
.setId(jti)
.signWith(SignatureAlgorithm.HS512, "asdf")
.compact();
}
public JwtDecoder jwtDecoder() {
// base64 decoder from org.apache.tomcat.util.codec.binary.Base64;
byte[] key = Base64.decodeBase64("asdf");
// var key = "asdf".getBytes(StandardCharsets.UTF_8);
var paddedKey = Arrays.copyOf(key, 128);
return NimbusJwtDecoder
.withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
.macAlgorithm(MacAlgorithm.HS512)
.build();
}
并使用它:
Main s = new Main();
String token = s.generateToken(new HashMap<>(), "hatef");
JwtDecoder decoder = s.jwtDecoder();
System.out.println(decoder.decode(token));
編輯3:
OP 在評論中報告:
它與
io.jsonwebtoken.impl.TextCodec.BASE64.decode(secretKey)而不是org.apache.tomcat.util.codec.binary.Base64.decodeBase64(secretKey),與后者我仍然有一個com.nimbusds.jose.proc.BadJWSException
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/349033.html
