Spring security 使用CSRF令牌和BasicAuth保护同一端点的Spring Boot

Spring security 使用CSRF令牌和BasicAuth保护同一端点的Spring Boot,spring-security,Spring Security,我有一个Spring Boot REST应用程序,它有两个主要部分: 我想用令牌保护ajax调用的UI 我希望具有基本身份验证的公共端点 据我所知,我不能用CSRF令牌保护公共端点,因为它们需要会话。问题是,某些端点需要两者都可以访问,因此,当UI使用CSRF时,如何使用CSRF保护它们,并禁用基本身份验证的CSRF 这是我目前拥有的,我完全禁用了csrf,所以基本工作 http.requestMatchers().antMatchers("/form/fill", "/form/fill/

我有一个Spring Boot REST应用程序,它有两个主要部分:

  • 我想用令牌保护ajax调用的UI
  • 我希望具有基本身份验证的公共端点
据我所知,我不能用CSRF令牌保护公共端点,因为它们需要会话。问题是,某些端点需要两者都可以访问,因此,当UI使用CSRF时,如何使用CSRF保护它们,并禁用基本身份验证的CSRF

这是我目前拥有的,我完全禁用了csrf,所以基本工作

http.requestMatchers().antMatchers("/form/fill", "/form/fill/*", "/form/fillParams", "/form/fillParams/*").and()
                .csrf().disable().authorizeRequests().anyRequest().hasAnyRole(SecurityConfiguration.ROLE_FORMS_AUTHOR,
                        SecurityConfiguration.ROLE_FORM_FILLER, SecurityConfiguration.ROLE_ADMIN)
                .and().httpBasic();

编辑:我找到了旧答案,我想知道是否有一种方法可以在我的案例中利用它,但我仍然不确定如何区分“本地”用户和通过httpBasic()验证的用户

在Spring Security java配置文件中,您可以如下配置
HttpSecurity
对象,以便仅在某些请求上启用
CSRF
检查(默认情况下,在所有传入请求上启用,而disable将对所有传入请求禁用,因此request Mather可以在此处帮助您找到要启用或禁用的路径
csrf

确保用csrf check/**替换
/URL,并按端点或多个路径替换路径

 @Override
    protected void configure(HttpSecurity http) throws Exception {

        RequestMatcher csrfRequestMatcher = new RequestMatcher() {
            private RegexRequestMatcher requestMatcher =
                    new RegexRequestMatcher("/urls-with-csrf-check/**", null);

            public boolean matches(HttpServletRequest httpServletRequest) {
                if (requestMatcher.matches(httpServletRequest)) {
                    return true;
                }
                return false;
            }
        };

        http.requestMatchers().antMatchers("/form/fill", "/form/fill/*", "/form/fillParams", "/form/fillParams/*").and()
                .csrf()
                .requireCsrfProtectionMatcher(csrfRequestMatcher)
                .and()
                .authorizeRequests().anyRequest().hasAnyRole(SecurityConfiguration.ROLE_FORMS_AUTHOR, SecurityConfiguration.ROLE_FORM_FILLER, SecurityConfiguration.ROLE_ADMIN)
                .and().httpBasic();
    }

有了@kj007的输入,我就可以让它工作了。 我使用的是
requireCsrfProtectionMatcher
,我的matcher就是这样的:

public class UIRequestMatcher implements RequestMatcher {

    public static final List<GrantedAuthority> USER_ROLES = new ArrayList<>();
    static {
        USER_ROLES.add(new SimpleGrantedAuthority(SecurityConfiguration.ROLE_ADMIN));
        USER_ROLES.add(new SimpleGrantedAuthority(SecurityConfiguration.ROLE_FILES_AUTHOR));
        USER_ROLES.add(new SimpleGrantedAuthority(SecurityConfiguration.ROLE_FORMS_AUTHOR));
        USER_ROLES.add(new SimpleGrantedAuthority(SecurityConfiguration.ROLE_TEMPLATES_AUTHOR));
    }

    @Override
    public boolean matches(HttpServletRequest request) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return "POST".equals(request.getMethod()) && auth.getAuthorities().stream().anyMatch(USER_ROLES::contains);
    }

}
公共类UIRequestMatcher实现RequestMatcher{
public static final List USER_ROLES=new ArrayList();
静止的{
添加(新的SimpleGrantedAuthority(SecurityConfiguration.ROLE\u ADMIN));
USER_ROLES.add(新的SimpleGrantedAuthority(SecurityConfiguration.ROLE_FILES_AUTHOR));
USER_ROLES.add(新的SimpleGrantedAuthority(SecurityConfiguration.ROLE_FORMS_AUTHOR));
USER_ROLES.add(新的SimpleGrantedAuthority(SecurityConfiguration.ROLE_TEMPLATES_AUTHOR));
}
@凌驾
公共布尔匹配(HttpServletRequest){
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
返回“POST”.equals(request.getMethod())&&auth.getAuthorities().stream().anyMatch(用户角色::包含);
}
}

因此,我正在检查
身份验证
是否具有我的任何用户角色,因为我的基本身份验证只应用于我的技术用户。

对于公共URL,make.permitAll()和任何请求都应进行身份验证。@kj007可能我将其表述为错误,但“public”仍然应该使用httpBasic保护令牌,但是httpBasic和CSRF令牌不会一起工作,除非您有额外的“握手”请求来检索令牌,这将使RESTfulity无效。谢谢,我现在只需要找到一种方法来识别本地用户。我设法使用“XMLHttpRequest”检查ajax。等于(request.getHeader(“X-request-With”))但是有一些正常的表单提交。我想到的唯一一件事是一个隐藏字段并检查它的存在,但这不是很安全。你可以为http basic定义角色??如果我理解正确,我可以检查用户角色,但我如何仅从HttpServletRequest获取角色?Spring安全将检查Principal具有“本地”权限(您可以在ant matcher hasRole(“本地”)中使用),但我如何在requireCsrfProtectionMatcher中组合此权限,例如为此权限启用CSRF?