我已经在SpringBoot中实现了一些简单的方法来验证用户身份,它返回JWT并验证用户,但应用程序停止给出实际正文的响应,并开始发送空的200个响应,知道为什么会这样吗?根据调试器的说法,程序永远不会在我试图调用的请求上结束,但JWT的授权总是成功的

我的班级

JWTService

@Service
public class JwtService {
private static final String SECRET_KEY = "32bitkey";
public String extractEmail(String token) {
return exctractClaim(token, Claims::getSubject);
}

    public <T> T exctractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }
    
    public String generateToken(
            UserDetails userDetails) {
        return generateToken(Map.of(), userDetails);
    }
    public String generateToken(
            Map<String, Object> extraClaims,
            UserDetails userDetails) {
        return Jwts
                .builder()
                .setClaims(extraClaims)
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
                .signWith(getSigningKey(), Signature算法rithm.HS256)
                .compact();
    }
    
    public boolean isTokenValid(String token, UserDetails userDetails) {
        final String email = extractEmail(token);
        return email.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }
    
    public boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }
    
    private Date extractExpiration(String token) {
       return exctractClaim(token, Claims::getExpiration);
    }
    
    private Claims extractAllClaims(String token) {
        return Jwts
                .parserBuilder()
                .setSigningKey(getSigningKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
    private Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
    }

Security filter chain

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity security) throws Exception {
        security
                .csrf()
                .disable()
                .authorizeHttpRequests()
                .requestMatchers(
                        "/fixture/getFixturesBySportAndDate",
                        "/user/register",
                        "/user/authenticate",
                        "/league/getLeaguesByFixturePlayedAtDateInSport",
                        "/team/fillTeamsHockey",
                        "/fixture/fillFixturesHockey",
                        "/fixture/fillFixturesBasketball")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthetificationFilter, UsernamePasswordAuthenticationFilter.class);

        return security.build();
    }

JwtAuthFilter

@Component
@RequiredArgsConstructor
public class JwtAuthetificationFilter extends OncePerRequestFilter {
    private final JwtService jwtService;
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain
    ) throws ServletException, IOException {
        final String authorizationHeader = request.getHeader("Authorization");
        final String jwt;
        final String email;
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }
        jwt = authorizationHeader.substring(7);
        email = jwtService.extractEmail(jwt);
        if (email != null && SecurityContextHolder.getContext().getAuthentication() == null){
            UserDetails userDetails = userDetailsService.loadUserByUsername(email);
            if (jwtService.isTokenValid(jwt, userDetails)){
                UsernamePasswordAuthenticationToken authenticationToken
                        = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
    }

Application Config

@Configuration @RequiredArgsConstructor
public class ApplicationConfig {

    private final UserRepository userRepository;

    @Bean
    public UserDetailsService userDetailsService() {
        return username -> userRepository.findByEmail(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
        };

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

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration cfg) throws Exception {
         return cfg.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
       return new BCryptPasswordEncoder();
    }

Example request

    @GetMapping(value = "/getUserInfo")
    public ResponseEntity<User> getUserInfo(HttpServletRequest request){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String email = authentication.getName();
        User user = userRepository.findByEmail(email).get();
        return ResponseEntity.ok(user);
    }

我试着基本上更改所有内容并调试信息,但无法完成,因为它只是给了我一个答案,即请求永远不会执行

推荐答案

我根本没有try 运行您的代码,但乍一看,在JwtAuthenticationFilter中设置安全上下文的身份验证后,您似乎没有调用筛选器链(尽管如果没有授权头,您会这样做).

try 调整此选项:

...
        if (email != null && SecurityContextHolder.getContext().getAuthentication() == null){
            UserDetails userDetails = userDetailsService.loadUserByUsername(email);
            if (jwtService.isTokenValid(jwt, userDetails)){
                UsernamePasswordAuthenticationToken authenticationToken
                        = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }

要调用链中的下一个筛选器:

        if (email != null && SecurityContextHolder.getContext().getAuthentication() == null){
            UserDetails userDetails = userDetailsService.loadUserByUsername(email);
            if (jwtService.isTokenValid(jwt, userDetails)){
                UsernamePasswordAuthenticationToken authenticationToken
                        = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        // causes the next filter in the chain to be invoked
        filterChain.doFilter(request, response);

下面是doFilter方法的FilterChain头中的注释:

    /**
     * Causes the next filter in the chain to be invoked, or if the calling
     * filter is the last filter in the chain, causes the resource at the end of
     * the chain to be invoked.
     *
     * @param request
     *            the request to pass along the chain.
     * @param response
     *            the response to pass along the chain.
     *
     * @throws IOException if an I/O error occurs during the processing of the
     *                     request
     * @throws ServletException if the processing fails for any other reason
     */
    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException;

Java相关问答推荐

我应该避免在Android中创建类并在运行时编译它们吗?

Java在模块化jar文件中找不到类,但是javap可以

neo4j java驱动程序是否会在错误发生时自动回滚事务?

Java List with all combinations of 8 booleans

如何以干净的方式访问深度嵌套的对象S属性?

Hibernate 6支持Joda DateTime吗?

第三方Jar pom.xml

Tinylog中的滚动文件会在每次应用启动时覆盖日志(log)文件

为什么我的回收视图会显示重复的列表?

在Java 15应用程序中运行Java脚本和Python代码

二进制数据的未知编码/序列化

为什么StandardOpenOption.CREATE不能通过Ubuntu在中小企业上运行?

一对多关系和ID生成

从Spring6中的JPMS模块读取类时出现问题

有没有办法在o(log(N))中以系统的方式将数组中的小块元素复制和移动到新增长的数组中的左侧?

PhantomReference无法访问时会发生什么?

Android上的SQLite:Android.database.SQLite.SQLiteReadOnlyDatabaseException:try 写入只读数据库(代码1032 SQLite_readonly_DBMOVED)

javax.crypto-密码对象-提供者服务是如何工作的?

在不带instanceof或switch的java中记录模式

UuidGenerator Bean 类型不匹配?