Spring JWT 签名验证失败
Posted
技术标签:
【中文标题】Spring JWT 签名验证失败【英文标题】:Spring JWT signature Validation fails 【发布时间】:2018-04-30 10:47:40 【问题描述】:我正在使用 Spring Cloud、oauth 和 JWT 构建微服务应用程序。我的 Oauth2 服务器生成 JWT 令牌,但是当我尝试验证网关中的令牌(使用 ZUUL 实现)时,我遇到了错误
能否请您告诉我出了什么问题以及可能的解决方案。 我使用的是 Spring 4.3、Spring boot 1.5.8、Spring cloud Dalston.SR4
org.springframework.security.jwt.crypto.sign.InvalidSignatureException: Calculated signature did not match actual value
at org.springframework.security.jwt.crypto.sign.MacSigner.verify(MacSigner.java:62) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
at org.springframework.security.jwt.JwtImpl.verifySignature(JwtHelper.java:287) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
at org.springframework.security.jwt.JwtHelper.decodeAndVerify(JwtHelper.java:77) ~[spring-security-jwt-1.0.8.RELEASE.jar:na]
at com.debopam.gateway.filter.CustomPostZuulFilter.run(CustomPostZuulFilter.java:57) ~[classes/:na]
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) [zuul-core-1.3.0.jar:1.3.0]
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193) [zuul-core-1.3.0.jar:1.3.0]
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157) [zuul-core-1.3.0.jar:1.3.0]
at com.netflix.zuul.FilterProcessor.postRoute(FilterProcessor.java:92) [zuul-core-1.3.0.jar:1.3.0]
at com.netflix.zuul.ZuulRunner.postRoute(ZuulRunner.java:87) [zuul-core-1.3.0.jar:1.3.0]
我在身份验证服务器和网关服务器中都使用了签名密钥 12345AsDfG。
下面是代码sn-p 身份验证服务器
@Configuration
public class JWTTokenStoreConfig
@Autowired
private ServiceConfig serviceConfig;
@Bean
public TokenStore tokenStore()
return new JwtTokenStore(jwtAccessTokenConverter());
@Bean
@Primary
public DefaultTokenServices tokenServices()
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setAccessTokenValiditySeconds(60*30);
return defaultTokenServices;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter()
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(serviceConfig.getJwtSigningKey());
return converter;
@Bean
public TokenEnhancer jwtTokenEnhancer()
return new JWTTokenEnhancer();
@Configuration
public class JWTOAuth2Config extends AuthorizationServerConfigurerAdapter
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private DefaultTokenServices tokenServices;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
//oauthServer.checkTokenAccess("permitAll()");
oauthServer
.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')")
.checkTokenAccess("permitAll()");
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter));
endpoints.tokenStore(tokenStore) //JWT
.accessTokenConverter(jwtAccessTokenConverter) //JWT
.tokenEnhancer(tokenEnhancerChain) //JWT
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("uiapp")
.secret("secret")
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
在网关应用程序中,我使用下面的代码来验证令牌
@Override
public Object run()
RequestContext ctx = RequestContext.getCurrentContext();
try
InputStream is = ctx.getResponseDataStream();
String responseBody = IOUtils.toString(is);
if (StringUtils.hasText(responseBody)
&& responseBody.contains("access_token"))
Map<String, Object> responseMap = objectMapper.readValue(
responseBody, new TypeReference<Map<String, Object>>() );
String accesToken = responseMap.get("access_token").toString();
Jwt jwt = JwtHelper.decodeAndVerify(accesToken, new MacSigner(serviceConfig.getJwtSigningKey()));
System.out.println(jwt.getClaims());
//System.out.println(jwt.getBody());
ctx.setResponseBody(responseBody);
catch (Exception e)
logger.error("Error occured in zuul post filter", e);
return null;
【问题讨论】:
我查看了 spring oauth 中的其他实现和测试,但一无所获。我会调试它。到达时令牌的格式是否正确?和生产的一样吗?两端的key一样吗? 抱歉,服务之间存在密钥不匹配。 【参考方案1】:服务之间存在签名密钥不匹配。
【讨论】:
以上是关于Spring JWT 签名验证失败的主要内容,如果未能解决你的问题,请参考以下文章
CAS 6.0 和 Spring Security:服务票证验证时 JWT 配置失败