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

时间:2019-01-04 22:43:17

标签: spring-boot authentication spring-security keycloak spring-rest

spring-boot服务的前端在第3方仪表板中呈现。该仪表板还具有我们要使用的通用搜索栏。现在,一旦我们实施了Keycloak身份验证,我们就开始专门在此搜索栏中遇到问题。所有其他API都可以正常工作,因为它们只能从我的前端调用,但是搜索API会被第三方仪表板调用。

很奇怪,第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异常,一旦解决,它就会再次引发未授权的用户错误。请帮助确定我在做什么错。

我还尝试过的东西:

  1.         super.configure(http);
            http.csrf().disable();
    
            http
    
    
               .cors()
                .and()
                .authorizeRequests()
                .antMatchers("/health", "/error").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated();
    
  2. @Override public void configure(final WebSecurity web) { web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**"); }

  3. `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 个答案:

答案 0 :(得分:0)

也许与您无关,但是我的问题是/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()
}