Spring Security配置-HttpSecurity与WebSecurity

Kih*_*ats 2 java spring-security spring-boot

我只需要了解Spring Security Configuration中的内容。使用下面的示例...

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
            .and()
            .authorizeRequests().antMatchers("/secret/**").authenticated()
            .and()
            .authorizeRequests().antMatchers("/**").permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }

}
Run Code Online (Sandbox Code Playgroud)

configure(WebSecurity web)方法的目的是什么?

我不能只是添加/resources/**configure(HttpSecurity http)方法,在这条线.authorizeRequests().antMatchers("/**", "/resources/**").permitAll(); 应该不是它的工作相同,即允许所有的请求/resources/**没有任何身份验证?

sha*_*zin 13

当您使用HttpSecurity并尝试permitAll()请求时。您的请求将被允许从 Spring Security Filter Chain 访问。这是成本高昂的,因为会有其他请求也会进入此过滤器链,需要根据身份验证/授权来允许或禁止这些请求。

HttpSecurity.authorizeRequests().antMatchers("/**", "/resources/**").permitAll();
Run Code Online (Sandbox Code Playgroud)

但是当您使用时,任何请求都resources将完全绕过 Spring Security Filter Chain。这是安全的,因为您不需要任何身份验证/授权即可查看图像或读取 javascript 文件。

WebSecurity.ignoring().antMatchers("/resources/**");
Run Code Online (Sandbox Code Playgroud)


hat*_*oor 11

我想通过包含一些代码来为伟大的答案做出贡献。在 Spring Security 中,有 3 个 Bean 非常重要。根据它们的类型DelegatingFilterProxyFilterChainProxy以及SecurityFilterChain

DelegatingFilterProxy将过滤请求的工作委托给类型FilterChainProxy为 的bean springSecurityFilterChain,其FilterChainProxy配置如下:

@Bean(
    name = {"springSecurityFilterChain"}
)
public Filter springSecurityFilterChain() throws Exception {
    boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
    if (!hasConfigurers) {
        WebSecurityConfigurerAdapter adapter = (WebSecurityConfigurerAdapter)this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {
        });
        this.webSecurity.apply(adapter);
    }

    return (Filter)this.webSecurity.build();
}
Run Code Online (Sandbox Code Playgroud)

springSecurityFilterChain(或FilterChainProxy) 本身有一个SecurityFilterChain. 它本身有一个执行实际逻辑的实例SecurityFilterChain列表。Filter

每次我们扩展WebSecurityConfigurerAdapter和重写该configure(HttpSecurity httpSecurity)方法时,我们实际上创建了一个SecurityFilterChain将要使用的方法springSecurityFilterChain

如何从列表中springSecurityFilterChain选择合适的?SecurityFilterChain基于接口boolean matches(HttpServletRequest request)中定义的方法SecurityFilterChain

因此HttpSecurity用于创建定制的SecurityFilterChain.

那么什么时候WebSecurity真正发挥作用呢?WebSecurity实际上允许我们定制springSecurityFilterChain(或FilterChainProxy)。看看是如何 springSecurityFilterChain创建的。

这是创建 bean 时调用performBuild的方法。WebSecurityspringSecurityFilterChain

@Override
protected Filter performBuild() throws Exception {
    Assert.state(
            !securityFilterChainBuilders.isEmpty(),
            () -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
                    + "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
                    + "More advanced users can invoke "
                    + WebSecurity.class.getSimpleName()
                    + ".addSecurityFilterChainBuilder directly");
    int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
    List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
            chainSize);
    for (RequestMatcher ignoredRequest : ignoredRequests) {
        securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
    }
    for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
        securityFilterChains.add(securityFilterChainBuilder.build());
    }
    FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
    if (httpFirewall != null) {
        filterChainProxy.setFirewall(httpFirewall);
    }
    filterChainProxy.afterPropertiesSet();

    Filter result = filterChainProxy;
    if (debugEnabled) {
        logger.warn("\n\n"
                + "********************************************************************\n"
                + "**********        Security debugging is enabled.       *************\n"
                + "**********    This may include sensitive information.  *************\n"
                + "**********      Do not use in a production system!     *************\n"
                + "********************************************************************\n\n");
        result = new DebugFilter(filterChainProxy);
    }
    postBuildAction.run();
    return result;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当 Spring 想要将每个Spring 注册SecurityFilterChain到bean 中时,Spring 将在列表的开头 添加一个自定义实现 。springSecurityFilterChainweb.ignoring()....DefaultSecurityFilterChainSecurityFilterChain

当请求出现时springSecurityFilterChain,将检查其列表,SecurityFilterChain以便将过滤作业委托给该请求SecurityFilterChainspringSecurityFilterChain将调用match每个方法 SecurityFilterChain。如果请求 URL 以“/resources/**”开头,则将过滤请求的工作委托给列表开头Spring的实例以及通过此行添加的自定义实例:DefaultSecurityFilterChainSecurityFilterChain

for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
    securityFilterChains.add(securityFilterChainBuilder.build());
}
Run Code Online (Sandbox Code Playgroud)

完全被忽略了。


Pat*_*mil 6

WebSecurity ignoring()方法的常规用法省略了Spring Security,并且Spring Security的功能均不可用。WebSecurity基于HttpSecurity。

@Override
public void configure(WebSecurity web) throws Exception {
    web
        .ignoring()
        .antMatchers("/resources/**")
        .antMatchers("/publics/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .antMatchers("/publics/**").hasRole("USER") // no effect
        .anyRequest().authenticated();
}
Run Code Online (Sandbox Code Playgroud)

上面的示例中的WebSecurity让Spring忽略/resources/**/publics/**。因此.antMatchers("/publics/**").hasRole("USER"),不考虑 HttpSecurity中的。

这将完全省略来自安全过滤器链的请求模式。请注意,与此路径匹配的所有内容都将不应用身份验证或授权服务,并且可以自由访问。

configure(HttpSecurity)允许基于选择匹配在资源级别上配置基于Web的安全性-例如,以下示例将以URL开头的URL限制为/admin/具有ADMIN角色的用户,并声明需要成功进行身份验证的所有其他URL

configure(WebSecurity)用于影响全局安全性的配置设置(忽略资源,设置调试模式,通过实现自定义防火墙定义拒绝请求)。例如,以下方法将导致以身份验证为开头的所有请求/resources/都被忽略

  • 在第二个示例中,“configure(HttpSecurity http)”是否被完全忽略,因为“configure(WebSecurity web)”已经表示应忽略所有这些相同的端点? (2认同)