postman JWT签名与本地计算的签名不匹配,JWT的有效性不能Assert,也不应该被信任,在 Spring Boot 中

jaxagkaj  于 2023-10-18  发布在  Postman
关注(0)|答案(1)|浏览(130)

我有一个问题与 JWT 认证令牌。当我第一次用postman测试登录时,它给了我令牌,但在重新启动intelij后,我在postman和intelij中得到了403禁止错误(JWT签名与本地计算的签名不匹配。JWT的有效性不能Assert,也不应该被信任。)(这里我用 Postman)。这是我的代码

package com.example.demo.Configiration;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@Component
public class JwtUtils {
    private String Secret = "671491AE98362741F722202EED3288E8FF2508B35315ADBF75EEB3195A926B40";

    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    public Boolean hasClaim(String token, String claimName) {
        final Claims claims = extractAllClaims(token);
        return claims.get(claimName) != null;
    }

    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return c

在此处键入

laimsResolver.apply(claims);
    }

    private Claims extractAllClaims(String token) {
        return Jwts.parser().setSigningKey(Secret).parseClaimsJws(token).getBody();
    }

    private Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }
    public String generateToken(UserDetails userDetails){
        Map<String,Object> claims=new HashMap<>();
        return createToken(claims,userDetails);
    }
    public String generateToken(UserDetails userDetails,Map<String,Object> claims){
        return createToken(claims,userDetails);
    }
    private String createToken(Map<String,Object> claims,UserDetails userDetails){
        return Jwts.builder().setClaims(claims).setSubject(userDetails.getUsername())
                .claim("authorities",userDetails.getAuthorities())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(24)))
                .signWith(SignatureAlgorithm.HS256,Secret).compact();
    }
    public Boolean isTokenValide(String token, UserDetails userDetails) {
        final String userName = extractUsername(token);
        return (userName.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
  /*  private Key getSigningKey() {
        byte[] keyBytes= Decoders.BASE64.decode(Secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }*/
}
package com.example.demo.Configiration;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class SecurityConfig {
    private final JwtAuthFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
         httpSecurity
                 .csrf().disable()
                .authorizeRequests()
                 .requestMatchers("/hello/login")
                 .permitAll()
                .anyRequest()
                .authenticated()
                 .and()
                 .sessionManagement()
                 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                 .and()
                 .authenticationProvider(authenticationProvider)
                 .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
         return httpSecurity.build();
    }
}
package com.example.demo.Configiration;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

import static org.springframework.http.HttpHeaders.AUTHORIZATION;
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
    private final UserDetailsService userDetailsService;
    private final JwtUtils jwtUtils;
    private final Dto dto;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
    final  String authHeader=request.getHeader(AUTHORIZATION);
    final  String userEmail;
    final  String jwtToken;
    if (authHeader==null || !authHeader.startsWith("Bearer")){
        filterChain.doFilter(request,response);
        return;
    }
    jwtToken=authHeader.substring(7);
    userEmail=jwtUtils.extractUsername(jwtToken);
    if (userEmail !=null && SecurityContextHolder.getContext().getAuthentication()==null){
        UserDetails userDetails=dto.findUserbyemail(userEmail);
      //  final Boolean isTokenValid;
        if (jwtUtils.isTokenValide(jwtToken,userDetails)){
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=
                    new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
            usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
    }
    filterChain.doFilter(request,response);
    }
}
package com.example.demo.Configiration;

import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Repository
public class Dto {
    private final static List<UserDetails> APPLICATION_USERS= Arrays.asList(
            new User(
                    "[email protected]",
                    "aymen",
                    Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN"))
            ),
            new User(
                    "[email protected]",
                    "messikh",
                    Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))
            )
    );
    public  UserDetails findUserbyemail(String email){
        return APPLICATION_USERS
                .stream().filter(u -> u.getUsername().equals(email))
                .findFirst().orElseThrow(() -> new UsernameNotFoundException("No user was found"));
    }
}
package com.example.demo.Configiration;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class AppConfig {
    private final Dto dto;

    @Bean
    public AuthenticationProvider authenticationProvider() {
        final DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
       // return NoOpPasswordEncoder.getInstance();
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
                return dto.findUserbyemail(email);
            }
        };
    }
        @Bean
        public AuthenticationManager authenticationManager (AuthenticationConfiguration configuration) throws Exception
        {
            return configuration.getAuthenticationManager();
        }
}
package com.example.demo;

import lombok.*;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AuthentificationRequest {
    private String email;
    private String password;
}
package com.example.demo.Controller;

import com.example.demo.AuthentificationRequest;
import com.example.demo.Configiration.Dto;
import com.example.demo.Configiration.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/hello")
@RequiredArgsConstructor
public class Hello {
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService userDetailsService;
    private  final JwtUtils jwtUtils;
    private final Dto dto;
    @GetMapping("/hello1")
    public ResponseEntity<String> hello1(){
        return ResponseEntity.ok("aaaaaaaaaaaaaaaa");
    }
    @PostMapping("/login")
    public ResponseEntity<String> login(@RequestBody AuthentificationRequest request){
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(request.getEmail(),request.getPassword())
        );
        final UserDetails user=dto.findUserbyemail(request.getEmail());
        if (user!=null){
            return ResponseEntity.ok(jwtUtils.generateToken(user));
        }
        return ResponseEntity.status(400).body("ssssssssss");
    }
}

4.0.0 org.springframework. Boot spring- Boot -starter-parent 3.0.6 com.example demo 2 0.0.1-SNAPSHOT demo 2 demo 2<java.version>17</java.version> org.springframework. Boot spring- Boot -starter-web org.springframework. Boot spring- Boot -starter-security

<dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>
z4iuyo4d

z4iuyo4d1#

问题可能来自以下事实:您正在使用.signWith(SignatureAlgorithm.HS256,Secret)对令牌进行签名,并且为了在extractAllClaims中获得声明,您仅直接使用机密,因此它无法检索适当的信息来验证令牌Jwts.parser().setSigningKey(Secret).parseClaimsJws(token).getBody();
另外,我想指出的是,根据文档,您用于签署令牌的方法已被弃用,请查看文档/Parser Doc,您可以进行适当的调整。同样作为参考,你可以把静态秘密检查为byte[],Key或String?

相关问题