spring-security Spring安全性:在SecurityContext中找不到身份验证对象

7vhp5slm  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(395)

下面的配置(filterChain)在SpringBoot-2.7.5中运行良好,但在我尝试在SpringBoot-3.0.0-RC 1中测试后,它不工作,并显示以下消息,如果想迁移到Spring-Boot-3.0.0,我需要更改任何内容。谢谢。
{“时间戳”:1667794247614,“状态”:401,“错误”:“未授权”,“提示信息”:“在SecurityContext”“中找不到身份验证对象,路径”:“/api/管理员/1”}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable()
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationProvider).and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
        .authorizeRequests()
        .antMatchers("/**").permitAll()            
        // private endpoints
        .anyRequest().authenticated();

    http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

下面是jwtTokenFilter:

@Component
public class**JwtTokenFilter**extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JPAUserDetailService jpaUserDetailService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // Get authorization header and validate
        final String header = request.getHeader(HttpHeaders.AUTHORIZATION);

        if (isEmpty(header) || !header.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }

        // Get jwt token and validate
        final String token = header.split(" ")[1].trim();

        if (!jwtTokenUtil.validate(token)) {

            chain.doFilter(request, response);

            return;
        }

        // Get user identity and set it on the spring security context
        UserDetails userDetails = jpaUserDetailService.loadUserByUsername(jwtTokenUtil.getUsername(token));

        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, (userDetails == null ? null : userDetails.getAuthorities()));

        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

        SecurityContextHolder.getContext().setAuthentication(authentication);

        chain.doFilter(request, response);
    }

}
9ceoxa92

9ceoxa921#

在SpringSecurity6中,默认行为是SecurityContextHolderFilter将只从SecurityContextRepository读取SecurityContext并将其填充到SecurityContextHolder中。如果用户希望SecurityContext在请求之间保持不变,则现在必须显式地将SecurityContextSecurityContextRepository一起保存。这通过只需要写入SecurityContextRepository来消除歧义并提高性能(即HttpSession)在必要时。

SecurityContextHolder.setContext(securityContext);
securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse);

请访问https://docs.spring.io/spring-security/reference/5.8/migration.html#_explicit_save_securitycontextrepository
如果不起作用,请尝试返回到5.x默认设置:

http
    .securityContext((securityContext) -> 
            .requireExplicitSave(false)
    )
xxhby3vn

xxhby3vn2#

我改变了一些代码如下,但仍然不工作。

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    // Get authorization header and validate
    final String header = request.getHeader(HttpHeaders.AUTHORIZATION);

    if (isEmpty(header) || !header.startsWith("Bearer ")) {
        chain.doFilter(request, response);
        return;
    }

    // Get jwt token and validate
    final String token = header.split(" ")[1].trim();

    if (!jwtTokenUtil.validate(token)) {

        chain.doFilter(request, response);

        return;
    }

    // Get user identity and set it on the spring security context
    UserDetails userDetails = jpaUserDetailService.loadUserByUsername(jwtTokenUtil.getUsername(token));

    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, (userDetails == null ? null : userDetails.getAuthorities()));

    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

    SecurityContextImpl scix = new SecurityContextImpl(authentication);

    SecurityContextHolder.setContext(scix);

    RequestAttributeSecurityContextRepository securityContextRepository = new RequestAttributeSecurityContextRepository();

    securityContextRepository.saveContext(scix, request, response);

    chain.doFilter(request, response);
}

配置如下:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

    http.cors().and().csrf().disable()
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationProvider)
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeHttpRequests((requests) -> requests
                .requestMatchers("/swagger-ui", "/rest-api-docs").permitAll()                   
                .anyRequest().authenticated()
        )

        .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
        .securityContext((securityContext) -> 
            securityContext.requireExplicitSave(false)
        )
        ;

    return http.build();
}

相关问题