我是Spring安全新手,问题是过滤器应用于所有请求URL i-e。 /api/user/signup
。我想排除/api/user/signup
路径以通过过滤器。我甚至尝试过跟随
web.ignoring()
.antMatchers("/api/user/**")
.antMatchers("/api/user/signup")
但过滤器再次应用于它。过滤器需要authkey令牌和注册请求 万分没有令牌。当它没有找到令牌时它将通过异常。以下是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)
;
}
这是我的令牌过滤器类
@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)
答案 0 :(得分:0)
其中一个解决方案是根据传入的URL跳过过滤器逻辑。 就在这一行之后:
HttpServletRequest req = (HttpServletRequest) request;
在您doFilter
的方法AuthenticationTokenProcessingFilter
中添加此代码:
if (new AntPathRequestMatcher("/api/user/signup").matches(req))) {
chain.doFilter(request, response);
return;
}
当然,对doFilter
方法中的网址进行硬编码并不是一个好习惯 - 您可以通过SecurityConfig.configure
方法将该网址传递给过滤器。此外,new AntPathRequestMatcher
可以进行优化 - 只需创建一次并放入字段变量。
答案 1 :(得分:0)
解决方案是模仿具有多个where col1 is not null or col2 is not null or col3 is not null)
块的良好旧命名空间方式。使用Java配置,您还可以拥有多个扩展<http ...>
的类。 Spring Security Reference Manual有一个example。摘录:
WebSecurityConfigurerAdapter
注意:
@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
的{{1}}实例,以指定应首先考虑WebSecurityConfigurerAdapter
。@Order
声明此WebSecurityConfigurerAdapter
仅适用于以http.antMatcher
开头的网址HttpSecurity
的另一个实例。如果网址不以/api/
开头,则会使用此配置(默认为WebSecurityConfigurerAdapter
无效)答案 2 :(得分:0)
通过使用&#39; @Component&#39;注释您的过滤器,您告诉Spring将其添加到嵌入式容器中。
任何Servlet,Filter或Servlet *作为Spring bean的监听器实例将在嵌入式容器中注册。如果要在配置期间引用application.properties中的值,这可能特别方便。
所以.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
这条线没有影响。
要解决此问题,请删除@Component和@Autowired并构建您自己的实例,并且不要将其设为bean。