如何避免使用 Spring Security 重定向到某些 URL 的登录表单?

Mic*_*Ros 5 spring spring-security spring-boot

这是我的 webapp 的 Spring Security 配置

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/", LOGIN, "/webjars/**").permitAll()
            .antMatchers(CONFIGURATION).hasAuthority(Authorities.AUTHORITY_SOLMAN72_EXPORT_ENABLED.getKey())
            .antMatchers("/api/**").hasAuthority(Authorities.AUTHORITY_SOLMAN72_EXPORT_ENABLED.getKey())
            .and()
        .formLogin()
            .loginPage(LOGIN)
            .and()
        .addFilterBefore(oAuth2ClientAuthenticationProcessingFilter, BasicAuthenticationFilter.class);
}
Run Code Online (Sandbox Code Playgroud)

目前,服务器正在将LOGIN每个没有正确凭据的请求重定向到该页面。

我只想将LOGIN未经授权的请求重定向到页面CONFIGURATION,而未经授权的请求/api/**应以 403 回答。

实现这一目标的好方法是什么?

ant*_*tak 7

我去实现 dur 的答案,但注意到有一个(可从Spring Security 3.2.xExceptionHandlingConfigurer.defaultAuthenticationEntryPointFor(...)左右获得)它可以用更少的依赖代码有效地完成相同的事情:

http.exceptionHandling()
        .defaultAuthenticationEntryPointFor(new Http403ForbiddenEntryPoint(), new AntPathRequestMatcher("/api/**"));
Run Code Online (Sandbox Code Playgroud)

此外,我注意到指定任何 defaultAuthenticationEntryPointFor() 设置第一个作为默认入口点

默认情况下,FormLoginConfigurerOAuth2LoginConfigurerSaml2LoginConfigurer等在 和期间添加自己的入口点SecurityConfigurer.init(),除非我们指定了一个,否则其中的第一个将成为默认入口点。

这可能有用,也可能没用,但因为 、、等AuthenticationEntryPoint提供的避免了包含 header 的请求,所以我们指定的入口点最终将用于 AJAX,无论我们为请求指定什么匹配器参数。FormLoginConfigurerOAuth2LoginConfigurerSaml2LoginConfigurerX-Requested-With: XMLHttpRequestdefaultAuthenticationEntryPointFor()


Mic*_*Ros 6

我使用以下方法解决了我的问题AuthenticationEntryPoint

http
    .authorizeRequests()
        .antMatchers(LOGIN).permitAll()
        .antMatchers("/**").hasAuthority(Authorities.AUTHORITY_SOLMAN72_EXPORT_ENABLED.getKey())
        .and()
    .addFilterBefore(oAuth2ClientAuthenticationProcessingFilter, BasicAuthenticationFilter.class)
    .exceptionHandling().authenticationEntryPoint(unauthenticatedRequestHandler);
Run Code Online (Sandbox Code Playgroud)
@Bean
UnauthenticatedRequestHandler unauthenticatedRequestHandler() {
    return new UnauthenticatedRequestHandler();
}

static class UnauthenticatedRequestHandler implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        if (request.getServletPath().startsWith("/api/")) {
            response.setStatus(403);
        } else {
            response.sendRedirect(LOGIN);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


dur*_*dur 6

您可以使用DelegatingAuthenticationEntryPoint

根据评估AuthenticationEntryPoint选择混凝土。AuthenticationEntryPointRequestMatcher

使用Http403ForbiddenEntryPointfor/api/**LoginUrlAuthenticationEntryPoint作为默认入口点。

@Bean
public DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() { 
    LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
    entryPoints.put(new AntPathRequestMatcher("/api/**"), new Http403ForbiddenEntryPoint());
    DelegatingAuthenticationEntryPoint defaultEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
    defaultEntryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint(LOGIN));
    return defaultEntryPoint;
}
Run Code Online (Sandbox Code Playgroud)