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()
...
}
}
}
备注:
- 正常配置
Authentication
- 创建包含
@Order
的 WebSecurityConfigurerAdapter
实例以指定应首先考虑哪个 WebSecurityConfigurerAdapter
。
-
http.antMatcher
声明此 HttpSecurity
仅适用于以 /api/
开头的 URL
- 创建
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。
我是 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()
...
}
}
}
备注:
- 正常配置
Authentication
- 创建包含
@Order
的WebSecurityConfigurerAdapter
实例以指定应首先考虑哪个WebSecurityConfigurerAdapter
。 -
http.antMatcher
声明此HttpSecurity
仅适用于以/api/
开头的 URL
- 创建
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。