Spring Security:为什么.authorizeRequests()。antMatchers(“/ api/v1/web/**”)。permitAll()不工作?
问题描述:
我很努力地使用没有JWT令牌的/api/v1/web/**
URI。这个URI必须是公开的。我知道这是很多应用程序中的一个常见功能,否则,我们如何创建登录,登录和重置密码页面?所以,我确信我犯了一些愚蠢的错误,因为我对Spring Boot/Security没有太多的经验。Spring Security:为什么.authorizeRequests()。antMatchers(“/ api/v1/web/**”)。permitAll()不工作?
这里是我的web安全配置代码:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// disable caching
http.headers().cacheControl();
/*ROUTING SECURITY*/
http.csrf().disable() // disable csrf for our requests.
.cors()
.and()
.authorizeRequests()
.antMatchers("/api/v1/web/**").permitAll()
.antMatchers("/api/v1/users/**").hasAnyAuthority("USERS_LIST,USERS_CREATE,USERS_EDIT,USERS_DELETE")
.antMatchers("/api/v1/locals/**").hasAnyAuthority("LOCALS_LIST,LOCALS_CREATE,LOCALS_EDIT,LOCALS_DELETE")
.antMatchers("/api/v1/utils/**").hasAnyAuthority("UTILS")
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/api/v1/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
// @Override
// public void configure(WebSecurity web) throws Exception {
// web.ignoring().antMatchers("/api/v1/web/**");
// }
}
这里是我的TokenAuthentication:
public class TokenAuthenticationService {
private final String secret = "secret_string";
private final String tokenPrefix = "Bearer ";
private final String headerString = "Authorization";
public void addAuthentication(HttpServletResponse response, Authentication authentication) {
GregorianCalendar expiration = new GregorianCalendar();
expiration.add(GregorianCalendar.HOUR_OF_DAY, 5);
//expiration.add(GregorianCalendar.SECOND, 10);
List<UserAuthority> authorities = new ArrayList<UserAuthority>();
for(GrantedAuthority authority : authentication.getAuthorities()) {
authorities.add(new UserAuthority(authority.getAuthority()));
}
AuthenticatedUser authenticatedUser = new AuthenticatedUser((String)authentication.getPrincipal(), authorities);
String dataToGenerateToken;
try {
dataToGenerateToken = new ObjectMapper().writeValueAsString(authenticatedUser);
// We generate a token now
String generatedToken = Jwts.builder()
.setSubject(dataToGenerateToken)
.setExpiration(expiration.getTime())
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
response.addHeader(headerString, tokenPrefix + generatedToken);
response.addHeader("Access-Control-Expose-Headers", "Authorization");
response.getWriter().write(dataToGenerateToken);
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(headerString).substring(7);
if (token != null) {
// parse the token.
String userData = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
if (userData != null) // we managed to retrieve a user
{
AuthenticatedUser authenticatedUser;
try {
authenticatedUser = new ObjectMapper().readValue(userData, AuthenticatedUser.class);
return authenticatedUser;
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
}
我只能访问/api/v1/web/**
,如果我包括智威汤逊认证,如果不是我得到下面的异常:
java.lang.NullPointerException: null
at br.com.bilheteriarapida.admin.security.jwt.TokenAuthenticationService.getAuthentication(TokenAuthenticationService.java:61) ~[classes/:na]
at br.com.bilheteriarapida.admin.security.jwt.JWTAuthenticationFilter.doFilter(JWTAuthenticationFilter.java:24) ~[classes/:na]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.14.jar:8.5.14]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.14.jar:8.5.14]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_51]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.14.jar:8.5.14]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_51]
如果我删除了这段代码的注释:
// @Override
// public void configure(WebSecurity web) throws Exception {
// web.ignoring().antMatchers("/api/v1/web/**");
// }
我只能执行SELECT查询下/api/v1/web/**
的URI,如果我尝试打电话节省对象(UPDATE或INSERT)我得到一个错误交易服务。非常奇怪,我知道。
有什么想法?
感谢
答
随着SO人的帮助,我能实现我在做什么错了,这里是我的最终解决方案:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// disable caching
http.headers().cacheControl();
/*ROUTING SECURITY*/
http.csrf().disable() // disable csrf for our requests.
.cors()
.and()
.authorizeRequests()
.antMatchers("/api/v1/web/**").permitAll()
.and()
.authorizeRequests()
.antMatchers("/api/v1/users/**").hasAnyAuthority("USERS_LIST,USERS_CREATE,USERS_EDIT,USERS_DELETE")
.antMatchers("/api/v1/locals/**").hasAnyAuthority("LOCALS_LIST,LOCALS_CREATE,LOCALS_EDIT,LOCALS_DELETE")
.antMatchers("/api/v1/utils/**").hasAnyAuthority("UTILS")
.anyRequest().authenticated()
.and()
.addFilterBefore(new JWTLoginFilter("/api/v1/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
,并在TokenAuthenticationService
类,我编辑了getAuthentication方法第一线于:
public Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(headerString);
if (token != null) {
token = token.substring(7);
....
}
现在,我的应用程序已经配置好,可以正确访问公共和私人URI。不需要web.ignoring()
了。
第61行是什么?它是'String token = request.getHeader(headerString).substring(7);'?你不能在'null'上调用'substring'。 – dur
最后一个错误是@dur。我不敢相信:(至少现在我可以使用'antMatchers()'正确配置安全性,而且我不需要再使用'web.ignoring()',但是非常感谢。 –
您能否接受这个问题实际上只是一个'NullPointerException',这个问题对其他用户没有任何价值,对你没有任何坏处,因为你的问题已经被解决了。 – dur