spring boot 2.4.0-使用basicauthenticationfilter设置securitycontextholder会引发illegalstateexception

deikduxw  于 2021-07-11  发布在  Java
关注(0)|答案(0)|浏览(204)

当前正在执行从spring boot v2.3.5到v2.4.0的升级。但是,当用户通过身份验证并实际通过filterchain时,我遇到了一个关于设置securitycontextholder的问题。
有问题的代码是扩展basicauthenticationfilter的类的一部分,如下所示:

/**
     * Perform the filter for authentication
     *
     * @param request  The HttpServletRequest
     * @param response The HttpServletResponse
     * @param chain    The FilterChain
     * @throws IOException      When the filter could not be performed
     * @throws ServletException When the filter could not be performed
     */
    @Override
    protected void doFilterInternal(final HttpServletRequest request,
                                    final HttpServletResponse response,
                                    final FilterChain chain) throws IOException, ServletException {
        final String header = request.getHeader(jwtConfiguration.getHeader());

        if (header == null || !header.startsWith(jwtConfiguration.getTokenPrefix())) {
            chain.doFilter(request, response);
            return;
        }

        final UsernamePasswordAuthenticationToken authentication = getAuthentication(request);

        if (authentication == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        } else {
            final SecurityContext context = SecurityContextHolder.createEmptyContext();

            context.setAuthentication(authentication);
            SecurityContextHolder.setContext(context);

            chain.doFilter(request, response); // The exception is thrown here, but only when setting the SecurityContextHolder
        }
    }

...

    /**
     * Get the UsernamePasswordAuthenticationToken from the HttpServletRequest
     *
     * @param request The HttpServletRequest
     * @return The UsernamePasswordAuthenticationToken that was filtered from the HttpServletRequest
     */
    private UsernamePasswordAuthenticationToken getAuthentication(final HttpServletRequest request) {
        final String token = request.getHeader(jwtConfiguration.getHeader());
        if (token != null && !token.isEmpty()) {
            final UserDto user = authorizationService.getCurrentUser(token);

            if (user != null) {
                final Set<GrantedAuthority> grantedAuthorities = new HashSet<>();

                if (user.getRoles() != null) {
                    for (final RoleDto role : user.getRoles()) {
                        if (role.getPermissions() != null) {
                            for (final PermissionDto permission : role.getPermissions()) {
                                grantedAuthorities.add(new SimpleGrantedAuthority(permission.getName()));
                            }
                        }
                    }
                }

                return new UsernamePasswordAuthenticationToken(user, null, grantedAuthorities);
            }
            return null;
        }
        return null;
    }

如果不设置securitycontextholder,代码可以正常工作,但不幸的是,身份验证将不会被设置,这不是我想要的结果,因为我想保护某些端点。
扩展WebSecurityConfigureAdapter的类的设置如下:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final JwtConfiguration jwtConfiguration;
    private final IAuthorizationService userService;

    /**
     * Initialize a new WebSecurityConfiguration
     *
     * @param jwtConfiguration The JwtConfiguration object
     * @param userService      The IAuthorizationService implementation
     */
    public WebSecurityConfiguration(@Autowired final JwtConfiguration jwtConfiguration,
                                    @Autowired final IAuthorizationService userService) {
        if (jwtConfiguration == null)
            throw new NullPointerException("JwtConfig cannot be null!");
        if (userService == null)
            throw new NullPointerException("IAuthorizationService cannot be null!");

        this.jwtConfiguration = jwtConfiguration;
        this.userService = userService;
    }

    /**
     * Configure the HttpSecurity
     *
     * @param http The HttpSecurity object
     * @throws Exception When the configuration failed
     */
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        final AuthenticationManager authenticationManager = authenticationManager();

        http
                .csrf().disable().cors().and()
                .authorizeRequests()
                .antMatchers("/authentication/**",
                        "/v2/api-docs",
                        "/configuration/ui",
                        "/swagger-resources/**",
                        "/configuration/security",
                        "/swagger-ui.html",
                        "/webjars/**")
                .permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(new JwtAuthorizationFilter(authenticationManager, jwtConfiguration, userService), JwtAuthorizationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

设置securitycontextholder时,通过链时发生的异常本身如下所示:
java.lang.illegalstateexception:找不到接口org.springframework.security.core.authentication的主构造函数或单个公共构造函数-也找不到默认构造函数

提前感谢您的任何提示或建议!

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题