如果授权标头中缺少不记名令牌,请勿将 API 请求重定向到登录页面

Jan*_*sen 0 spring spring-security keycloak

我正在用 Spring Security 编写一个 Spring Boot 应用程序,它有一个 REST API 和一个 Web 界面。当用户未通过身份验证时,REST API 应返回,401 Unauthorized而 Web 界面应重定向到登录页面。使用下面的配置,这在以下情况下有效:

  • 如果不记名令牌无效或过期
  • 如果不存在授权标头

如果请求包含授权标头但没有 bearer令牌,我无法做到的是具有相同的行为。在这种情况下,请求总是被重定向到登录页面,无论是 API 请求还是“网络”请求。到目前为止,我发现的唯一防止这种情况的选择是设置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")
    }
}
Run Code Online (Sandbox Code Playgroud)

jzh*_*aux 5

当有不记名令牌时触发Spring Security BearerTokenAuthenticationFilter(和相应的BearerTokenAuthenticationEntryPoint)。

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

http
    .exceptionHandling((exceptions) -> exceptions
        .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
    );
Run Code Online (Sandbox Code Playgroud)

这将告诉 Spring Security 使用BearerTokenAuthenticationEntryPointfor any AuthenticationException

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

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

也就是说,通过使用没有 Keycloak 包装器的 Spring Security,您可能会取得更大的成功。这样做的原因是 Spring Security 现在附带了自己的不记名令牌支持