英文:
Spring Security intercept except annotated
问题
假设我有一些受标准HttpSecurity保护的端点,如下所示:
http.csrf().disable().authorizeRequests().anyRequest().permitAll()
以及特定端点上的验证器。
我收到一个请求,要为大多数端点创建一个新的验证器,但我想,如果我像下面这样保护端点可能会更安全:
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().addFilterBefore(myGenericFilterBean, MyAuthenticationProcessingFilter.class)
(假设MyGenericFilterBean是扩展了GenericFilterBean的某个内容)
但我希望能够跳过对任何使用我创建的注解的端点应用此myGenericFilterBean,例如我会创建一个名为@DontCheckMyFilter的注解。
这样做有可能吗,而不会让事情变得过于复杂从而不值得吗?
英文:
Let's say I have a standard HttpSecurity protected endpoints, like:
http.csrf().disable().authorizeRequests().anyRequest().permitAll()
and validators on specific endpoints.
I got a request to make a new validator for most of our endpoints, but instead of adding an annotation everywhere I thought that it could be safer if I secure the endpoints like
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().addFilterBefore(myGenericFilterBean, MyAuthenticationProcessingFilter.class)
(Given that MyGenericFilterBean is something extending GenericFilterBean)
but I want to make it skip this myGenericFilterBean for any endpoint I annotate with an annotation I would create for example @DontCheckMyFilter
Is it even possible without going way too far to make it worth it?
答案1
得分: 1
在您的情况下,最好的选择是使用特定的 path
来避免访问那些端点,而不是使用自定义注释。原因是 Spring 过滤器提供了很多处理路径和角色的功能。
因此,如果您可以改变您的方法,一个可能的解决方案是:
@Component
public class MyGenericFilterBean extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 在这里执行您需要的操作
filterChain.doFilter(request, response);
}
// 您应该重写的方法,以避免执行此过滤器
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
Set<String> avoidFilterForUrls = new HashSet<>(Arrays.asList("/no-filter/**"));
AntPathMatcher pathMatcher = new AntPathMatcher();
return avoidFilterForUrls.stream().anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
}
}
在上面的示例中,对于以 /no-filter
开头的请求,过滤器不会被执行(实际上 doFilterInternal
方法不会被调用)。
在这一点上,您需要考虑正确配置您的安全选项。按照您的示例进行配置:
http.csrf().disable()
.authorizeRequests()
// 不需要身份验证的服务列表
//.antMatchers(GET, "/no-filter/**").permitAll()
// 其他任何请求都需要身份验证
.anyRequest().authenticated()
.and()
.addFilterBefore(myGenericFilterBean, MyAuthenticationProcessingFilter.class)
自定义 shouldNotFilter
方法,过滤器将不会被执行,但是请注意,“您正在谈论”的 MyAuthenticationProcessingFilter
可能也需要将这些端点包含在“白名单”中,如下所示:
// 不需要身份验证的服务列表
// 取消注释并根据您自己的端点进行自定义
//.antMatchers(GET, "/no-filter/**").permitAll()
因为如果您在这些端点中包含了“基于角色的安全性”或其他任何安全性,您需要将其移除,因为 Spring 仍然会验证这些端点的安全性。我的意思是,如果您不想对这些端点应用 MyAuthenticationProcessingFilter
,则不应该为它们包含任何 Spring 安全功能。
英文:
The best option in your case is use an specific path
to avoid those endpoints, instead of a custom annotation. The reason is Spring filters provide a lot of functionality to work/deal with path and roles mainly.
So if you can change your approach, a possible solution could be:
@Component
public class MyGenericFilterBean extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// Do here what you need
filterChain.doFilter(request, response);
}
// Method you should overwrite to avoid the execution of this filter
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
Set<String> avoidFilterForUrls = new HashSet<>(Arrays.asList("/no-filter/**"));
AntPathMatcher pathMatcher = new AntPathMatcher();
return avoidFilterForUrls.stream().anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
}
}
In the above example, the filter won't be executed (really doFilterInternal
won't be invoked) for the requests with Urls started with /no-filter
.
At this point, you need to take into account configure your security options correctly. Follow your example:
http.csrf().disable()
.authorizeRequests()
// List of services do not require authentication
//.antMatchers(GET, "/no-filter/**").permitAll()
// Any other request must be authenticated
.anyRequest().authenticated()
.and()
.addFilterBefore(myGenericFilterBean, MyAuthenticationProcessingFilter.class)
Customizing shouldNotFilter
the filter won't be executed but, taking into account you "are talking" about MyAuthenticationProcessingFilter
, probably will be necessary to include those endpoints into the "whitelist" too, as you can see in:
// List of services do not require authentication
// Uncomment and customize with your own ones
//.antMatchers(GET, "/no-filter/**").permitAll()
Because if you have included a "role based security" or any other one in those endpoints, you need to remove it because Spring still verifies the security for them. I mean, if you don't want to apply MyAuthenticationProcessingFilter
to those endpoints, no Spring security functionality should be included for them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论