首页 > 解决方案 > Spring Security - @PreAuthorize 返回 404

问题描述

当我使用 Spring Method Security 时,我目前遇到了一个奇怪的问题, @PreAuthorize("hasRole('MODERATOR')")

如果用户尝试访问需要“MODERATOR”角色的控制器,则返回资源,一切都很好(如果用户实际上具有该角色)。但是,如果用户没有这个角色,服务器会返回 404 - Not Found。这很奇怪,因为我预计服务器会返回其他内容,也许是 403 Forbidden?知道为什么会发生这种情况吗?这是我的安全配置:

@EnableWebSecurity
@Order(2)
public class WebSecurity extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        super();
        this.userDetailsService = userDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/api/**")
                .cors()
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Bean 
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.applyPermitDefaultValues();
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }      

}

和我的控制器:

@GetMapping
@PreAuthorize("hasRole('MODERATOR')")
public List<ApplicationUser> getAllUsers(HttpServletRequest request) {
    try (final ConnectionResource connectionResource = connectionFactory.create(); final UserDAO dao = new UserDAO()) {
        dao.setEm(connectionResource.em);
        return dao.getAllUsers();
    } catch (Exception ex) {
        Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, "unable to get all users", ex);
        return null;
    }
}

谢谢!

标签: javaspringsecurity

解决方案


可以借助注解启用全局方法安全性@EnableGlobalMethodSecurity(prePostEnabled=true)。结合起来@Preauthorize将为您的控制器创建一个新代理,并且它将丢失请求映射(在您的情况下为 GetMapping),这将导致 404 异常。

要处理此问题,您可以使用@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)

Spring 文档中的注释控制器

一个相关的 Github 问题


推荐阅读