1

複数のフィルターが HttpSecurity 構成メソッドに追加されると、一度に 1 つしか機能しないため、それらが重複しているように見えます。

これは設定方法です:

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .logout().and().antMatcher("/**")
            .addFilterBefore(ssoFilter(), RequestHeaderAuthenticationFilter.class)
            .authenticationProvider(preauthAuthProvider())
            .authorizeRequests()
            .antMatchers("/index.html", "/home.html", "/", "/login").permitAll()
            .anyRequest().authenticated().and().csrf()
            .csrfTokenRepository(csrfTokenRepository()).and()
            .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}

順序を指定しようとしましたが、問題は解決しません:

@Bean
public FilterRegistrationBean securityFilterChain(@Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter);
    registration.setOrder(Integer.MAX_VALUE - 2);
    registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
    return registration;
}

@Bean
public FilterRegistrationBean ssoFilterRegistrationBean() throws Exception {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(ssoFilter());
    registrationBean.setOrder(Integer.MAX_VALUE-1);
    return registrationBean;
}

@Bean
public FilterRegistrationBean csrfFilterRegistrationBean() throws Exception {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(csrfHeaderFilter());
    registrationBean.setOrder(Integer.MAX_VALUE);
    return registrationBean;
}

次のスレッドをたどりましたが、成功しませんでした。

spring-boot でのフィルター順序

https://github.com/spring-projects/spring-boot/issues/1640

https://github.com/spring-projects/spring-boot/issues/677

どんな助けでも大歓迎です!

アップデート:

CSRF フィルター定義

private Filter csrfHeaderFilter() {
    return new OncePerRequestFilter() {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            CsrfToken csrf = (CsrfToken) request
                    .getAttribute(CsrfToken.class.getName());
            if (csrf != null) {
                Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                String token = csrf.getToken();
                if (cookie == null
                        || token != null && !token.equals(cookie.getValue())) {
                    cookie = new Cookie("XSRF-TOKEN", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
            filterChain.doFilter(request, response);
        }
    };
}

SSO フィルターの定義:

public class SSORequestHeaderAuthenticationFilter extends RequestHeaderAuthenticationFilter {

private boolean allowPreAuthenticatedPrincipals = true;

public SSORequestHeaderAuthenticationFilter() {
    super();
    //TODO Pull this value from a properties file (application.properties, or localstrings.properties)
    //NOTE SM_USER is the default, but you can change it like this (your company may use some other header)
    //this.setPrincipalRequestHeader("SM_USER");
}


@Override
public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    chain.doFilter(request, response);
}

/**
 * This is called when a request is made, the returned object identifies the
 * user and will either be {@literal null} or a String. This method will throw an exception if
 * exceptionIfHeaderMissing is set to true (default) and the required header is missing.
 *
 * @param request {@link javax.servlet.http.HttpServletRequest}
 */
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
    String userName = (String) (super.getPreAuthenticatedPrincipal(request));
    if (userName == null || userName.trim().equals("")) {
        return userName;
    }

    return userName;
}

public boolean isAllowPreAuthenticatedPrincipals() {
    return allowPreAuthenticatedPrincipals;
}
}
4

3 に答える 3

0

あなたがやりたいことをするフィルターはすでに存在します。そのOAuth2AuthenticationProcessingFilter。このフィルターは、アプリケーションに で注釈を付ける場合に使用されます@EnableResourceServer。これを行うと、トークンベースの認証のみが機能するようになります。false他の認証方法も許可するには、このフィルターのステートレス フラグを に設定する必要があります。

私がしたことは、ApiTokenAccessFilter拡張するクラスを作成することOAuth2AuthenticationProcessingFilterです。このフィルターは、ResourceServerTokenServicesコンストラクター パラメーターを受け取り、stateless フラグを false に設定します。

public class ApiTokenAccessFilter extends OAuth2AuthenticationProcessingFilter {

  public ApiTokenAccessFilter(ResourceServerTokenServices resourceServerTokenServices) {

    super();
    setStateless(false);
    setAuthenticationManager(oauthAuthenticationManager(resourceServerTokenServices));
  }

  private AuthenticationManager oauthAuthenticationManager(ResourceServerTokenServices tokenServices) {

    OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager();

    oauthAuthenticationManager.setResourceId("oauth2-resource");
    oauthAuthenticationManager.setTokenServices(tokenServices);
    oauthAuthenticationManager.setClientDetailsService(null);

    return oauthAuthenticationManager;
  }
}

私のセキュリティ構成では、このフィルターを次のように使用しました。

@Configuration
@EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private ResourceServerTokenServices tokenServices;

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(new ApiTokenAccessFilter(tokenServices), AbstractPreAuthenticatedProcessingFilter.class);
  }
}

これは簡単だと思うので、spring-security-oauth Github repo で問題を開きました。この解決策が正しいかどうかはわかりませんが、別の方法は見つかりませんでした。

于 2016-02-03T17:29:55.713 に答える