spring - Io.jsonwebtoken.security.SignatureException:JWT 签名与本地计算的签名不匹配
问题描述
大家好,我需要帮助。
我正在学习Spring WebFlux和jwt 身份验证,所以我正在做一个 REST 服务来练习,但是这个错误不会让我继续,我不知道如何修复它。
错误:
io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:411) ~[jjwt-impl-0.11.1.jar:0.11.1]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/api/v1/character/users" [ExceptionHandlingWebHandler]
Stack trace:
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:411) ~[jjwt-impl-0.11.1.jar:0.11.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:541) ~[jjwt-impl-0.11.1.jar:0.11.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:601) ~[jjwt-impl-0.11.1.jar:0.11.1]
at com.rostenross.webflux.configuration.JWTUtil.getClaimsFromToken(JWTUtil.java:53) ~[classes/:na]
at com.rostenross.webflux.configuration.JWTUtil.getUsernameFromToken(JWTUtil.java:58) ~[classes/:na]
at com.rostenross.webflux.configuration.AuthenticationManager.authenticate(AuthenticationManager.java:32) ~[classes/:na]
at com.rostenross.webflux.configuration.SecurityContextRepository.lambda$3(SecurityContextRepository.java:55) ~[classes/:na]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1784) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:118) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:191) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110) ~[reactor-core-3.4.1.jar:3.4.1]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) ~[reactor-core-3.4.1.jar:3.4.1]
at
现在,这是我的代码:
**JWTUtil:**
@Component
public class JWTUtil {
private Logger log = LoggerFactory.getLogger(JWTUtil.class);
private String secrete = "RostenRoss35689682_Nestor_Matias_Costantini_16/04/1991_programador-universitario_profesor-de-quimica";
private String expireTimeInMilliSec="30000";
public String generateToken(User user) {
Date now =new Date();
Map<String, Object> claim = new HashMap<>();
claim.put("alg", "HS256");
claim.put("typ", "JWT");
return Jwts.builder()
.signWith(SignatureAlgorithm.HS256,Base64.getEncoder().encode(secrete.getBytes()))
.setClaims(claim)
.setSubject(user.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 864000000))
.claim("rol", user.getAuthorities().stream().collect(Collectors.toList()))
.compact();
}
public Claims getClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(Base64.getEncoder().encodeToString(secrete.getBytes()))
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody();
}
public String getUsernameFromToken(String token) {
return getClaimsFromToken(token).getSubject();
}
public Date getExpirationDate(String token) {
return getClaimsFromToken(token).getExpiration();
}
public Boolean isTokenExpired(String token) {
Date expirationDate = getExpirationDate(token);
log.info("isTokenExpired: "+expirationDate.before(new Date()));
return expirationDate.before(new Date());
}
public Boolean isTokenValidated(String token) {
return !isTokenExpired(token);
}
}
**SecurityContextRepository:**
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
private Logger log = LoggerFactory.getLogger(SecurityContextRepository.class);
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
// TODO Auto-generated method stub
return Mono.empty();
}
@Override
public Mono<SecurityContext> load(ServerWebExchange exchange ) {
String bearer = "Bearer ";
return Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION))
.filter(b -> b.startsWith(bearer))
.map(subs -> {
log.info("Substring: "+subs.substring(7));
return subs.substring(7);
}
)
.flatMap(token ->
Mono.just(
new UsernamePasswordAuthenticationToken(token,
token
,Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))
)
)
)
.flatMap(auth -> authenticationManager.authenticate(auth).map(SecurityContextImpl::new));
}
}
**身份验证管理器:**
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager{
private final Logger log = LoggerFactory.getLogger(AuthenticationManager.class);
@Autowired
private JWTUtil jwtUtil;
@Autowired
private UserRepository userRepository;
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
// TODO Auto-generated method stub
log.info("autenticaion inicio");
String token =authentication.getCredentials().toString();
String userName= jwtUtil.getUsernameFromToken(token);
return userRepository.findByUsername(userName)
.flatMap(userDetails -> {
log.info("role: "+userDetails.getAuthorities().toString());
if(userName.equals(userDetails.getUsername()) && jwtUtil.isTokenValidated(token)) {
return Mono.just(authentication);
}else {
log.info("userDetails: "+userDetails.toString());
return Mono.just(authentication);
}
});
}
}
安全配置
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
private final Logger log = LoggerFactory.getLogger(SecurityConfig.class);
@Autowired
private UserRepository repo;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private SecurityContextRepository securityContextRepository;
@Bean
ReactiveUserDetailsService userDdetailService() {
return (name) -> repo.findByUsername(name);
}
@Bean
public SecurityWebFilterChain securityWebFilterChain (ServerHttpSecurity http) {
return http.authorizeExchange(
authorizedExchangeSpec -> authorizedExchangeSpec
.pathMatchers("/api/v1/character/singin","/api/v1/character/login", "/api/v1/character/about","/api/v1/character/all","/api/v1/character/id=**","/api/v1/character/name=**")
.permitAll()
.anyExchange().authenticated()
)
.exceptionHandling()
.authenticationEntryPoint((response, error) -> Mono.fromRunnable(()->{
response.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
})).accessDeniedHandler((response,error) -> Mono.fromRunnable(()->{
response.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
})).and()
.httpBasic().disable()
.formLogin().disable()
.csrf().disable()
.authenticationManager(authenticationManager)
.securityContextRepository(securityContextRepository)
.requestCache().requestCache(NoOpServerRequestCache.getInstance())
.and()
.build();
}
}
** pom.xml:**
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.rostenross.webflux</groupId>
<artifactId>CharactersAPI</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>CharactersAPI</name>
<description>TV and comics charactes reactive API.</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
如果您需要更多信息,请告诉我。我在网上到处找,一无所获。
提前谢谢你们。
解决方案
推荐阅读
- java - 如何调用另一个 .java 文件中存在的类(不是嵌套类)?
- drupal - 如何访问自定义视图树枝中的字段值。德鲁巴8?
- azure - 如何捕获 Azure FunctionApp 的 OutOfMemoryException
- celery - 我想删除所有花芹菜历史/日志,但它不起作用
- ssl - nixos etcd.pem (kubernetes)
- java - 为什么永远不会调用@AfterReturning
- c# - 如何使用mvc中的entityframework从表中删除所有记录
- python - 尝试使用 python 登录 Confluence
- intellij-idea - IDEA 安装脚本
- javascript - 在javascript中将数组添加到对象数组