Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

spring - Io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature

Hi guys, I need help.

I′m learning Spring WebFlux and jwt authentication, so I'm doing a REST service to practice, but this error won't let me continue, I don't know how to fix it.

Error:

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 

Now, this is my code:

**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));
    }   
}

**AuthenticationManager: **

@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);
                    }
                });
    }
    
    
}

SecurityConfig

@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.</

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...