java - 使用@PreAuthorize 时,Spring Security 返回 404 而不是 403

标签 java spring-boot spring-security

在为此苦苦挣扎了几天之后(搜索 SO 以寻找类似的问题,进行反复试验),我很想放弃......

所以问题是我有一个基于 Spring Boot 的 REST 服务,使用 Spring Security 和 JWT 进行身份验证。现在我想确保某些方法只能由使用 @PreAuthorize 注释的授权人员调用。 这似乎部分有效,因为 Spring 没有调用方法返回 404。我本以为是 403。

我读过这个SO-question并尝试了那里给出的答案,但没有帮助。我已将 @EnableGlobalMethodSecurity(prePostEnabled = true)-Annotation 从我的 SecurityConfiguration 移动到 Application 类,如其他地方所建议的那样,它仍然不起作用。

我的安全配置如下所示:

@Configuration
@Profile("production")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Value("${adDomain}")
private String adDomain;

@Value("${adUrl}")
private String adUrl;

@Value("${rootDn}")
private String rootDn;

@Value("${searchFilter}")
private String searchFilter;

private final AuthenticationManagerBuilder auth;

private final SessionRepository sessionRepository;

@Autowired
public SecurityConfiguration(AuthenticationManagerBuilder auth, SessionRepository sessionRepository) {
    this.auth = auth;
    this.sessionRepository = sessionRepository;
}

@Override
public void configure(WebSecurity webSecurity) throws Exception
{
    webSecurity
            .ignoring()
            // All of Spring Security will ignore the requests
            .antMatchers("/static/**", "/api/web/logout")
            .antMatchers(HttpMethod.POST, "/api/web/login");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable() // Using JWT there is no need for CSRF-protection!
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .addFilter(new JwtAuthorizationFilter(authenticationManagerBean(), sessionRepository));
}

@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    ActiveDirectoryLdapAuthenticationProvider adProvider =
            new ActiveDirectoryLdapAuthenticationProvider(adDomain, adUrl, rootDn);
    adProvider.setConvertSubErrorCodesToExceptions(true);
    adProvider.setUseAuthenticationRequestCredentials(true);
    adProvider.setSearchFilter(searchFilter);
    adProvider.setUserDetailsContextMapper(new InetOrgPersonContextMapper());
    auth.authenticationProvider(adProvider);
    return super.authenticationManagerBean();
}

Controller 方法如下所示

@RequestMapping(path = "/licenses", method = RequestMethod.GET)
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> getAllLicenses(@RequestParam("after") int pagenumber, @RequestParam("size") int pagesize
        , @RequestParam("searchText") String searchText) {       
    List<LicenseDTO> result = ...
    return new ResponseEntity<Object>(result, HttpStatus.OK);
}

我很确定我遗漏了一些非常简单的东西,但我就是想不通是什么。

顺便说一句:如果请求许可证的用户具有 ADMIN 角色,则一切都按预期工作,所以问题不是真正的 404。

最佳答案

您需要在安全配置中定义异常处理,如下所示,

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable() // Using JWT there is no need for CSRF-protection!
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .exceptionHandling().accessDeniedHandler(new AccessDeniedExceptionHandler())
            .and()
            .addFilter(new JwtAuthorizationFilter(authenticationManagerBean(), sessionRepository));
}

您可以如下定义 AccessDeniedExceptionHandler 类,

public class AccessDeniedExceptionHandler implements AccessDeniedHandler
{
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException ex) throws IOException, ServletException {
        response.setStatus(HttpStatus.FORBIDDEN);
    }
}

关于java - 使用@PreAuthorize 时,Spring Security 返回 404 而不是 403,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55905824/

相关文章:

java - 如何将正确的 Spring 上下文连接到我的 Cucumber 测试?

spring-security - 多个 WebSecurityConfigurerAdapter 冲突问题

spring-security-oauth2 2.0.7 刷新 token UserDetailsS​​ervice 配置 - UserDetailsS​​ervice 是必需的

java - 在现有项目中实现 Spring Security 登录页面

Java - 相同模式之间的模式匹配

Java getRuntime 执行

java - 使用 ObjectOutputStream 将对象从列表写入文件

java - 具有相同类名(不同包)的两个 Spring 服务 Bean 即使使用限定符也会抛出错误

java - Spring Boot Keycloak - 如何获取分配给用户的角色列表?

java - 如何在 Spring Boot 中验证 JSON 请求?