9

トークンを取得して検証するカスタム フィルターを実行しようとしています。私はこの応答のアプローチに従っています。

これは関連する設定です:

セキュリティ構成:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = {"com.company.app"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Inject
AuthenticationTokenFilter authenticationTokenFilter;

@Inject
TokenAuthenticationProvider tokenAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(authenticationTokenFilter, BasicAuthenticationFilter.class)
                .antMatcher("/*")
                .authenticationProvider(tokenAuthenticationProvider)
                .authorizeRequests()
                    .anyRequest().authenticated();
    }

}

AuthenticationTokenFilter:

@Component
public class AuthenticationTokenFilter implements Filter {

private static final Logger logger = LoggerFactory.getLogger(AuthenticationTokenFilter.class);

@Override
public void init(FilterConfig fc) throws ServletException {
    logger.info("Init AuthenticationTokenFilter");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
    SecurityContext context = SecurityContextHolder.getContext();
    if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
        // do nothing
    } else {
        Map<String,String[]> params = req.getParameterMap();
        if (!params.isEmpty() && params.containsKey("auth_token")) {
            String token = params.get("auth_token")[0];
            if (token != null) {
                Authentication auth = new TokenAuthentication(token);
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }
    }

    fc.doFilter(req, res);
}

@Override
public void destroy() {

}
}

トークン認証:

public class TokenAuthentication implements Authentication {
private String token;

public TokenAuthentication(String token) {
    this.token = token;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return new ArrayList<GrantedAuthority>(0);
}
@Override
public Object getCredentials() {
    return token;
}
@Override
public Object getDetails() {
    return null;
}
@Override
public Object getPrincipal() {
    return null;
}
@Override
public boolean isAuthenticated() {
    return false;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
    return null;
}
}

TokenAuthenticationProvider:

@Component
public class TokenAuthenticationProvider implements AuthenticationProvider {

private static final Logger logger = LoggerFactory.getLogger(TokenAuthenticationProvider.class);

@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
    if (auth.isAuthenticated())
        return auth;

    String token = auth.getCredentials().toString();
    User user = userSvc.validateApiAuthenticationToken(token);
    if (user != null) {
        auth = new PreAuthenticatedAuthenticationToken(user, token);
        auth.setAuthenticated(true);
        logger.debug("Token authentication. Token: ");
    } else
        throw new BadCredentialsException("Invalid token " + token);
    return auth;
}

@Override
public boolean supports(Class<?> aClass) {
    return true;
}

}

しかし、AuthenticationTokenFilter がチェーンに追加されていないようです。デバッグ 呼び出しを行うと、SecurityConfig および configure メソッドに入りますが、フィルターには入りません。何が欠けている?

4

4 に答える 4

4

認証を無効にして、セキュリティ ルールへの認証にanonymous変更してみてください。fully

このようなもの :

http
    .addFilterBefore(authenticationTokenFilter, BasicAuthenticationFilter.class)
                    .antMatcher("/token")
                    .authenticationProvider(tokenAuthenticationProvider)
                    .authorizeUrls().anyRequest().fullyAuthenticated()
    .and()
                    .anonymous().disable()  
于 2014-03-12T19:28:08.043 に答える
2

あなたが欠けているのは

<filter>
       <filter-name>springSecurityFilterChain</filter-name>
       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
       <filter-name>springSecurityFilterChain</filter-name>
       <url-pattern>/*</url-pattern>
</filter-mapping>

クラスパスの初期化子の web.xml または同等のもので:

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

@Order(value = 1)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}

これは WebApplicationInitializer とは別のものです。ご了承ください:

  • SecurityConfig (または @EnableWebSecurity で注釈が付けられたもの) は、(ディスパッチャ コンテキストではなく) ルート コンテキストで定義する必要があります。
  • おそらく初期化の順序を理解する必要があります(理解できるかどうかはわかりません):

「WebApplicationInitializer の順序付け」
AbstractSecurityWebApplicationInitializer が呼び出された後にサーブレット Filter マッピングが追加された場合、それらは springSecurityFilterChain の前に誤って追加される可能性があります。アプリケーションに保護する必要のない Filter インスタンスが含まれていない限り、springSecurityFilterChain は他の Filter マッピングの前に配置する必要があります。@Order アノテーションを使用して、任意の WebApplicationInitializer が決定論的な順序でロードされるようにすることができます。

例:

@Order(value = 10)
public class AppWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
      return new Class<?>[] { AppConfig.class, SecurityConfig.class };
  }

  @Override
  protected Class<?>[] getServletConfigClasses() {
      return new Class<?>[] { RestConfig.class };
  }

  @Override
  protected String[] getServletMappings() {
      return new String[] { "/rest/*"};
  }
}


要約すると、Spring ドキュメントから:

サーブレット フィルターを使用する場合、明らかに web.xml で宣言する必要があります。そうしないと、サーブレット コンテナーによって無視されます。Spring Security では、フィルター クラスもアプリケーション コンテキストで定義された Spring Bean であるため、Spring の豊富な依存性注入機能とライフサイクル インターフェースを利用できます。Spring の DelegatingFilterProxy は、web.xml とアプリケーション コンテキストの間のリンクを提供します。

セキュリティ フィルタ チェーン

于 2014-10-23T00:05:19.477 に答える