在 spring-boot 中禁用特定 url 的 Keycloak 身份验证

Posted

技术标签:

【中文标题】在 spring-boot 中禁用特定 url 的 Keycloak 身份验证【英文标题】:Disable Keycloak authentication for a specific url in spring-boot 【发布时间】:2019-05-31 12:14:53 【问题描述】:

我的 spring-boot 服务的前端在 3rd 方仪表板中呈现。该仪表板还有一个我们想要使用的通用搜索栏。现在,一旦我们实现了 Keycloak 身份验证,我们就开始在这个搜索栏中特别遇到问题。所有其他 API 都可以正常工作,因为它们仅从我的前端调用,但搜索 API 由 3rd 方仪表板调用。

奇怪的是,第 3 方使用 Http OPTION 方法调用我的方法,但我的端点注册为 GET。

对于临时修复,我们正在尝试仅禁用搜索 API 上的身份验证,但似乎根本不起作用。我的配置器是:

@KeycloakConfiguration
@Profile("!local") // in local profile InsecureLocalConfigurer must be included instead
public class KeycloakSecurityConfigurer extends KeycloakWebSecurityConfigurerAdapter 


    /**
     * Enable Keycloak configuration over Spring Boot config instead of @code keycloak.json file.
     *
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#spring-boot-integration">
     * Spring Boot Integration</a>
     */
    @Bean
    @Nonnull
    public KeycloakConfigResolver keycloakConfigResolver() 
        return new KeycloakSpringBootConfigResolver();
    

    /**
     * Registers the KeycloakAuthenticationProvider with the authentication manager.
     */
    @Autowired
    public void configureGlobal(@Nonnull final AuthenticationManagerBuilder auth) 
        auth.authenticationProvider(keycloakAuthenticationProvider());
    

    /**
     * Accept only bearer token authentication.
     *
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#spring-security-configuration">
     *     Spring Security Configuration</a>
     * @see NullAuthenticatedSessionStrategy
     * @return @link NullAuthenticatedSessionStrategy instance.
     */
    @Override
    @Nonnull
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() 
        return new NullAuthenticatedSessionStrategy();
    

    /**
     * All request are checked regarding valid token, except <code>/health</code> check.
     * If configuration property <code>rca.security.enable</code> is set to <code>false</code>false
     * (default is true) then all requests are permitted without authentication.
     *
     * <p>
     * <b>CSRF security is disabled</b> since our app is not multipart web form app.
     * See more at: <ul>
     *
     * <li><a href="https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html#boot-features-security-csrf">
     * Cross Site Request Forgery Protection</a></li>
     * <li><a href="https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html">
     * Cross Site Request Forgery (CSRF)</a></li>
     * </ul>
     *
     * @param http the @link HttpSecurity to modify
     * @throws Exception if an error occurs
     */
    @Override
    protected void configure(@Nonnull final HttpSecurity http) throws Exception 
        super.configure(http);

        http.csrf().disable();

        http
                .cors()
                .and()
                .authorizeRequests()
                .antMatchers("/health", "/error").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated();
    

    /**
     * Avoid double @link KeycloakAuthenticationProcessingFilter bean registration.
     *
     * <p>
     * This will set @link AbstractAuthenticationProcessingFilter#continueChainBeforeSuccessfulAuthentication to
     * @code false, meaning that <b>after success authentication by this Keycloak filter -
     * further filters will be skipped</b>. See
     * @link KeycloakAuthenticationProcessingFilter#KeycloakAuthenticationProcessingFilter(
     * org.springframework.security.authentication.AuthenticationManager,
     * org.springframework.security.web.util.matcher.RequestMatcher) KeycloakAuthenticationProcessingFilter constructor
     *
     * @param filter @link KeycloakAuthenticationProcessingFilter auth processing filter
     * @return disabled @link FilterRegistrationBean
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration">
     * Avoid double Filter bean registration</a>
     */
    @Bean
    @Nonnull
    public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
            @Nonnull final KeycloakAuthenticationProcessingFilter filter) 

        final FilterRegistrationBean<KeycloakAuthenticationProcessingFilter> registrationBean =
                new FilterRegistrationBean<>(filter);

        registrationBean.setEnabled(false);
        return registrationBean;
    

    /**
     * Avoid double @link KeycloakPreAuthActionsFilter bean registration.
     *
     * @param filter @link KeycloakPreAuthActionsFilter filter
     * @return disabled @link FilterRegistrationBean
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration">
     * Avoid double Filter bean registration</a>
     */
    @Bean
    @Nonnull
    public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
            @Nonnull final KeycloakPreAuthActionsFilter filter) 
        final FilterRegistrationBean<KeycloakPreAuthActionsFilter> registrationBean =
                new FilterRegistrationBean<>(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    

    /**
     * Avoid double @link KeycloakAuthenticatedActionsFilter bean registration.
     *
     * @param filter @link KeycloakAuthenticatedActionsFilter filter
     * @return disabled @link FilterRegistrationBean
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration">
     * Avoid double Filter bean registration</a>
     */
    @Bean
    public FilterRegistrationBean keycloakAuthenticatedActionsFilterBean(
            @Nonnull final KeycloakAuthenticatedActionsFilter filter) 
        final FilterRegistrationBean<KeycloakAuthenticatedActionsFilter> registrationBean =
                new FilterRegistrationBean<>(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    

    /**
     * Avoid double @link KeycloakSecurityContextRequestFilter bean registration.
     *
     * @param filter @link KeycloakSecurityContextRequestFilter filter
     * @return disabled @link FilterRegistrationBean
     * @see <a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#avoid-double-filter-bean-registration">
     * Avoid double Filter bean registration</a>
     */
    @Bean
    public FilterRegistrationBean keycloakSecurityContextRequestFilterBean(
            @Nonnull final KeycloakSecurityContextRequestFilter filter) 

        final FilterRegistrationBean<KeycloakSecurityContextRequestFilter> registrationBean =
                new FilterRegistrationBean<>(filter);

        registrationBean.setEnabled(false);
        return registrationBean;
    

我尝试了多种方法,但都没有奏效。有时我开始收到 CORS 异常,一旦我修复它,它就会再次开始引发未经授权的用户错误。请帮助确定我做错了什么。

我尝试过的东西:

            super.configure(http);
            http.csrf().disable();
    
            http
    
    
               .cors()
                .and()
                .authorizeRequests()
                .antMatchers("/health", "/error").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated();
    

    @Override public void configure(final WebSecurity web) web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");

    `http.csrf().disable();

    http
            .cors()
            .and()
            .authorizeRequests()
            .antMatchers("/health", "/error").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/item/search").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/item/search/").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/item/search/**").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/**/search").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/**/search/").permitAll()
            .antMatchers(HttpMethod.OPTIONS, "/**/search/**").permitAll()
            .anyRequest().authenticated();`
    

【问题讨论】:

【参考方案1】:

也许与你无关,但我的问题是 /error 路径也应该被列入白名单。

事实上,我的呼叫错误导致重定向到/error,并且由于/error 是安全的,我得到了重定向到登录。

@Override
protected void configure(HttpSecurity http) throws Exception 
    super.configure(http);
    http
        .authorizeRequests()
        .antMatchers("/public/**").permitAll()
        .antMatchers("/secure/**").hasAuthority(...)
        .antMatchers("/error").permitAll()

【讨论】:

以上是关于在 spring-boot 中禁用特定 url 的 Keycloak 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring-Boot 2 中禁用安全性? [复制]

如何在 spring-boot 中禁用 spring-data-mongodb 自动配置

为特定请求/URL/端点禁用登录 gunicorn

Webflux禁用特定URL上的CSRF

Spring Security 3.2 CSRF 禁用特定 URL

从 Spring-Boot 测试中排除 elasticsearchTemplate