如果授权中缺少承载令牌,请不要将 API 请求重定向到登录页面 header

Do not redirect API request to login page if bearer token is missing in authorisation header

我正在编写 Spring 具有 Spring 安全性的引导应用程序,它具有 REST API 和 Web 界面。当用户未通过身份验证时,REST API 应该只是 return 401 Unauthorized 而 Web 界面应该重定向到登录页面。使用下面的配置,这在以下情况下有效:

如果请求包含授权 header 但 没有 bearer 令牌,我无法做到的是具有相同的行为。在这种情况下,请求总是被重定向到登录页面,无论它是 API 请求还是“web”请求。到目前为止我发现的防止这种情况的唯一选择是将 bearer-only 设置为 true,但是这样就不会再将请求重定向到登录页面...

我可以尝试其他配置吗?谢谢!

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = [KeycloakSecurityComponents::class])
open class SecurityConfiguration : KeycloakWebSecurityConfigurerAdapter() {
    @Autowired
    fun configureGlobal(auth: AuthenticationManagerBuilder) {
        auth.authenticationProvider(keycloakAuthenticationProvider())
    }

    @Bean
    open fun keycloakConfigResolver(): KeycloakSpringBootConfigResolver {
        return KeycloakSpringBootConfigResolver()
    }

    @Bean
    override fun sessionAuthenticationStrategy(): SessionAuthenticationStrategy {
        return RegisterSessionAuthenticationStrategy(SessionRegistryImpl())
    }

    override fun authenticationEntryPoint(): AuthenticationEntryPoint? {
        val requestMatcher = NegatedRequestMatcher(
            OrRequestMatcher(
                WEBAPP_ANT_PATHS.map {
                    AntPathRequestMatcher(it)
                }
            )
        )

        return KeycloakAuthenticationEntryPoint(adapterDeploymentContext(), requestMatcher)
    }

    override fun configure(http: HttpSecurity) {
        super.configure(http)
        http.cors().and().csrf().disable()
            .authorizeRequests()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
            .antMatchers("/actuator/health").permitAll()
            .antMatchers("/**").authenticated()
    }

    companion object {
        val WEBAPP_ANT_PATHS = listOf("/swagger-ui/**", "/swagger-ui.html")
    }
}

Spring 安全的 BearerTokenAuthenticationFilter(以及相应的 BearerTokenAuthenticationEntryPoint)在存在不记名令牌时被触发。

如果你想在其他时间调用BearerTokenAuthenticationEntryPoint,你可以在全局异常处理程序中注册它:

http
    .exceptionHandling((exceptions) -> exceptions
        .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
    );

这将告诉 Spring 安全对任何 AuthenticationException.

使用 BearerTokenAuthenticationEntryPoint

或者,如果您支持多种身份验证机制(例如表单登录),那么您可以指定 RequestMatcher:

http
    .exceptionHandling((exceptions) -> exceptions
        .defaultAuthenticationEntryPointFor(
            new BearerTokenAuthenticationEntryPoint(),
            (request) -> request.getHeader("Authorization") != null
        )
    );

也就是说,使用 Spring 安全性而不使用 Keycloak 包装器可能会取得更大的成功。这样做的原因是 Spring 安全性现在随 its own bearer token support.

一起提供