Spring Security 拦截除了被注解标记的部分。

huangapple go评论81阅读模式
英文:

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&lt;String&gt; avoidFilterForUrls = new HashSet&lt;&gt;(Arrays.asList(&quot;/no-filter/**&quot;));
    AntPathMatcher pathMatcher = new AntPathMatcher();
    return avoidFilterForUrls.stream().anyMatch(p -&gt; 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, &quot;/no-filter/**&quot;).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, &quot;/no-filter/**&quot;).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.

huangapple
  • 本文由 发表于 2020年7月25日 22:27:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63089515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定