我有以下Spring Security配置:
httpSecurity
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated()
.and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
即使在与authenticationTokenFilterBean()
表达式不匹配的端点上,也会应用/api/**
。我还尝试添加以下配置代码
@Override
public void configure(WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/some_endpoint");
}
但这仍然没有解决我的问题。如何告诉spring security仅在与安全URI表达式匹配的端点上应用过滤器?谢谢
答案 0 :(得分:22)
我有一个具有相同要求的应用程序并解决它我基本上将Spring Security限制为给定的蚂蚁匹配模式(使用antMatcher
),如下所示:
http.antMatcher("/api/**").authorizeRequests() //
.anyRequest().authenticated() //
.and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
您可以按如下方式阅读:对于http
,仅对与蚂蚁模式/api/**
匹配的请求调用这些配置,授权any request
至authenticated
用户and
{ {1}} add filter
authenticationTokenFilterBean()
before
。对于所有其他请求,此配置无效。
答案 1 :(得分:1)
如果您使用
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
您可以在构造函数中定义将应用于的特定路径:
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/api/**");
this.setAuthenticationManager(authenticationManager);
}
@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return super.requiresAuthentication(request, response);
}
requireAuthentication方法将用于了解该端点是否需要身份验证
答案 2 :(得分:1)
GenericFilterBean
具有以下方法:
/**
* Can be overridden in subclasses for custom filtering control,
* returning {@code true} to avoid filtering of the given request.
* <p>The default implementation always returns {@code false}.
* @param request current HTTP request
* @return whether the given request should <i>not</i> be filtered
* @throws ServletException in case of errors
*/
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return false;
}
因此,在扩展了GenericFilterBean
的过滤器中,您可以覆盖该方法并实现逻辑以仅在所需的路由上运行过滤器。
答案 3 :(得分:1)
我的要求是排除与/ api / auth / **匹配的端点,以实现相同的目的,我已经如下配置了WebSecurityConfig spring配置组件:
/**
* The purpose of this method is to exclude the URL's specific to Login, Swagger UI and static files.
* Any URL that should be excluded from the Spring security chain should be added to the ignore list in this
* method only
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/auth/**","/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js");
}
/**
* The purpose of this method is to define the HTTP configuration that defines how an HTTP request is
* going to be treated by the Spring Security chain. All the request URL's (excluding the URL's added
* in WebSecurity configuration ignore list) matching this configuration have to pass through the
* custom Spring security filter defined in this method
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
/**
* The purpose of this method is to create a new instance of JWTAuthenticationFilter
* and return the same from the method body. It must be ensured that this filter should
* not be configured as a Spring bean or registered into the Spring Application context
* failing which the below filter shall be registered as a default web filter, and thus
* all the URL's even the excluded ones shall be intercepted by the below filter
*/
public JWTAuthenticationFilter authenticationTokenFilterBean() {
return new JWTAuthenticationFilter();
}
答案 4 :(得分:0)
我想我已经找到一种解决方法。我有一个JwtTokenAuthenticationProcessingFilter
的{{1}}。如果头中有令牌,我希望它对请求进行身份验证,但是如果失败,则不要阻止该请求。无论身份验证结果是什么,您只需重写 doFilter 并调用 AbstractAuthenticationProcessingFilter
(调用unsuccessfulAuthentication是可选的) 。这是我的代码的一部分。
chain.doFilter
4月22日更新
要注册过滤器,只需将以下代码添加到WebSecurityConfig
public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
private final TokenExtractor tokenExtractor;
@Autowired
public JwtTokenAuthenticationProcessingFilter(TokenExtractor tokenExtractor, RequestMatcher matcher) {
super(matcher);
this.tokenExtractor = tokenExtractor;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!this.requiresAuthentication(request, response)) {
chain.doFilter(request, response);
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Request is to process authentication");
}
boolean success = true;
Authentication authResult = null;
try {
authResult = this.attemptAuthentication(request, response);
} catch (InternalAuthenticationServiceException var8) {
this.logger.error("An internal error occurred while trying to authenticate the user.", var8);
success = false;
} catch (AuthenticationException var9) {
success = false;
}
if (success && null != authResult) {
this.successfulAuthentication(request, response, chain, authResult);
}
// Please ensure that chain.doFilter(request, response) is invoked upon successful authentication. You want
// processing of the request to advance to the next filter, because very last one filter
// FilterSecurityInterceptor#doFilter is responsible to actually invoke method in your controller that is
// handling requested API resource.
chain.doFilter(request, response);
}
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
String tokenPayload = request.getHeader(WebSecurityConfig.AUTHENTICATION_HEADER_NAME);
RawAccessJwtToken token = new RawAccessJwtToken(tokenExtractor.extract(tokenPayload));
return getAuthenticationManager().authenticate(new JwtAuthenticationToken(token));
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authResult);
SecurityContextHolder.setContext(context);
}
}
在代码中,我只透露了添加过滤器的关键部分。 所有这些实现均受this site的启发。感谢作者弗拉基米尔·斯坦科维奇(Vladimir Stankovic)的详细解释。
答案 5 :(得分:-1)
要绕过某些特定端点的弹簧安全性,请执行以下操作:
httpSecurity
.authorizeRequests()
.antMatchers("/some_endpoints").permitAll()
.anyRequest().authenticated()
.and()
...