spring 个过滤器适用于所有 api 个网址错误

spring filters applies to all api urls Errors

我是 spring 安全的新手,问题是过滤器应用于所有请求 url,即。 /api/user/signup。我想排除 /api/user/signup 路径以通过过滤器。我什至尝试关注

web.ignoring()
            .antMatchers("/api/user/**")
            .antMatchers("/api/user/signup")

但过滤器再次应用于它。过滤器需要 authkey 令牌和注册请求 显然没有令牌。当它找不到 token.Following is spring security java config class

时,它将通过异常
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
AuthenticationTokenProcessingFilter authenticationTokenFilter;
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
    .antMatchers("/api/user/**")
    .antMatchers("/api/user/signup")

    ;
}
@Override
protected void configure(HttpSecurity http) throws Exception {


    http
    .csrf().disable()
    .authorizeRequests()   

    //allow anonymous POSTs to login
    .antMatchers("/api/user/signup").permitAll()

    //allow anonymous GETs to API
    .antMatchers(HttpMethod.GET, "/api/**").permitAll()
    .and()
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)     
    .and()
     .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)    
      ;
}

这是我的令牌过滤器 class

@Component
public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

  //  @Autowired UserService userService;
   @Autowired 
   TokenHandler tokenUtils;
   @Autowired
    AuthenticationManager authManager;

    public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
        this.authManager = authManager;
    }

    public AuthenticationTokenProcessingFilter() {
        super();
        // TODO Auto-generated constructor stub
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        @SuppressWarnings("unchecked")

        HttpServletRequest req = (HttpServletRequest) request;

        SecurityContext context = SecurityContextHolder.getContext();

        if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
            // do nothing
        }else {

            //System.out.println("Not Authenticated");
        if(req != null && req.getHeader("authKey") != null && req.getHeader("authKey").length() >0 ) {
            String token = req.getHeader("authKey"); 
           System.out.println("Found Token:"+req.getHeader("authKey"));
            // validate the token
            User userDetails = tokenUtils.parseUserFromToken(token);

                     List<GrantedAuthority> grantedAuths = new ArrayList<>();
                     grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
                     Authentication  authentication = 
                        new UsernamePasswordAuthenticationToken(userDetails.getEmail(), userDetails.getPassword(),grantedAuths);

                // set the authentication into the SecurityContext

                SecurityContextHolder.getContext().setAuthentication(authentication);         


           System.out.println("Is Authenticated:?"+  context.getAuthentication().isAuthenticated());
        // continue thru the filter chain
           chain.doFilter(request, response);
           System.out.println(" request is delegeted");
        }else{ 

                // Do your business stuff here for all paths other than /specialpath.
                System.out.println(" Token Not Found");
                throw new ServletException("Token not found in Request");           

        }

    }
}

以下是/api/user/signup出现

时的错误日志
Token Not Found
2015-05-17 09:38:36.742 ERROR 5096 --- [nio-8090-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Token not found in Request] with root cause

javax.servlet.ServletException: Token not found in Request
    at com.bitsparlour.sadaf.cloud.application.AuthenticationTokenProcessingFilter.doFilter(AuthenticationTokenProcessingFilter.java:93)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

解决方案之一是根据传入 URL 跳过过滤器逻辑。 就在行之后:

HttpServletRequest req = (HttpServletRequest) request;

在您 AuthenticationTokenProcessingFilter 的方法 doFilter 中添加此代码:

if (new AntPathRequestMatcher("/api/user/signup").matches(req))) {
    chain.doFilter(request, response);
    return;
}

当然,在 doFilter 方法中硬编码 URL 并不是一个好的做法 - 您可以将 URL 从 SecurityConfig.configure 方法传递给您的过滤器。 new AntPathRequestMatcher 也可以优化 - 只需创建一次并放入一个字段变量。

解决方案是模仿具有多个 <http ...> 块的良好旧名称空间方式。使用 Java 配置,您还可以有多个 类 扩展 WebSecurityConfigurerAdapter。 Spring 安全参考手册对此有一个 example。摘录:

@EnableWebSecurity
public class MultiHttpSecurityConfig {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) { 1
        ...
    }

    @Configuration
    @Order(1)                                                        2
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/**")                               3
                ...
        }
    }

    @Configuration                                                   4
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .formLogin()
                ...
        }
    }
}

备注:

  1. 正常配置Authentication
  2. 创建包含 @OrderWebSecurityConfigurerAdapter 实例以指定应首先考虑哪个 WebSecurityConfigurerAdapter
  3. http.antMatcher 声明此 HttpSecurity 仅适用于以 /api/
  4. 开头的 URL
  5. 创建 WebSecurityConfigurerAdapter 的另一个实例。如果 URL 不以 /api/ 开头,将使用此配置(没有 @Order 默认为最后)

通过使用“@Component”注释您的过滤器,您是在告诉 Spring 将其添加到嵌入式容器中。

Any Servlet, Filter or Servlet *Listener instance that is a Spring bean will be registered with the embedded container. This can be particularly convenient if you want to refer to a value from your application.properties during configuration.

所以.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)这一行没有影响。

要修复它,请删除 @Component 和 @Autowired 并构建您自己的实例,不要将其设为 bean。