Spring安全性使用HttpSecurity授权对url和方法的请求

ilo*_*una 31 spring spring-security spring-java-config jhipster

有没有办法授权使用特定网址的帖子请求org.springframework.security.config.annotation.web.builders.HttpSecurity

我用的HttpSecurity是:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint)
        .and()
            .rememberMe()
            .rememberMeServices(rememberMeServices)
            .key(env.getProperty("jhipster.security.rememberme.key"))
        .and()
            .formLogin()
            .loginProcessingUrl("/api/authentication")
            .successHandler(ajaxAuthenticationSuccessHandler)
            .failureHandler(ajaxAuthenticationFailureHandler)
            .usernameParameter("j_username")
            .passwordParameter("j_password")
            .permitAll()
        .and()
            .logout()
            .logoutUrl("/api/logout")
            .logoutSuccessHandler(ajaxLogoutSuccessHandler)
            .deleteCookies("JSESSIONID")
            .permitAll()
        .and()
            .headers()
            .frameOptions()
            .disable()
            .authorizeRequests()
                .antMatchers("/api/register").permitAll()
                .antMatchers("/api/activate").permitAll()
                .antMatchers("/api/authenticate").permitAll()
                .antMatchers("/api/logs/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/api/subscriptions").permitAll()
                .antMatchers("/api/**").authenticated();
}
Run Code Online (Sandbox Code Playgroud)

我想允许POST请求到/ api/subscription路径.只有POST.谢谢.

Mat*_*t C 58

看看这里https://github.com/spring-projects/spring-data-examples/tree/master/rest/security其中有

http
  .httpBasic().and()
  .authorizeRequests()
    .antMatchers(HttpMethod.POST, "/employees").hasRole("ADMIN")
    .antMatchers(HttpMethod.PUT, "/employees/**").hasRole("ADMIN")
    .antMatchers(HttpMethod.PATCH, "/employees/**").hasRole("ADMIN");
Run Code Online (Sandbox Code Playgroud)


Ale*_*nko 40

长话短说

Spring 6.0发布配置方法antMatchers(),mvcMathcers()regexMatchers()已从API 中删除。

并且提供了几种requestMatchers()方法作为替代。

gh-11939 -从 Java 配置中删除已弃用的antMatchers、mvcMatchers、regexMatchers 辅助方法。相反,请使用 requestMatchersHttpSecurity#securityMatchers

另外,还引入了重载方法authorizeHttpRequests()来替换Deprecated authorizeRequests()

即使您在项目中使用早期的 Spring 版本并且不会很快更新到Spring 6 ,antMatchers() 这也不是您可以选择用于保护应用程序请求的最佳工具。

在应用安全规则时,antMatchers()您需要非常小心,因为如果您保护路径,那么"/foo"这些限制将不会应用于该路径的其他别名,例如"/foo/", "/foo.thml"。因此,很容易错误配置安全规则并引入漏洞例如,本应仅由管理员访问的路径变得可供任何经过身份验证的用户使用,令人惊讶的是上述答案均未提及这一点)。

春季 6.0 -requestMatchers()

根据文档,限制对某些 URL 的访问的推荐方法5.8是使用HttpSecurity.authorizeHttpRequests(),它及其前身有两种风格:

  • 无参数版本,返回一个负责配置请求的对象(准确地说,是这个长名称类的实例)。所以我们可以requestMatchers()直接对其进行链式调用。

  • 第二个需要一个接口实例Customizer,允许通过使用 lambda 表达式应用增强的 DSL(特定于域的语言)。请参阅这篇文章,它使用过时的匹配方法,但很好地说明了 Lambda DSL 的关键思想,它通过可视化分组配置选项使配置更直观地阅读,并且无需使用方法and()

authorizeHttpRequests()使用哪个版本是一种风格选择(两者都是有效的并且在 中受支持6.0)。

现在requestMatchers()开始发挥作用,该方法有四个重载版本,可以替换任何已删除的匹配方法:

  • requestMatchers( String ... )- 需要一个可变参数的String模式。该匹配器使用与 Spring MVC 相同的匹配规则。即它的行为方式与 old 相同mvcMatchers(),因此该模式/foo将匹配该路径的所有现有别名,例如"/foo", "/foo/", "/foo.html"。所有其他版本都requestMatchers()具有相同的匹配行为,它消除了错误配置的可能性,这是antMatchers(). 请注意,相应的限制(hasRole()access()等)将应用于任何匹配的请求,无论其 HttpMethod 如何。

例子:

.requestMatchers("/foo/*").hasRole("ADMIN") // only authenticated user with role ADMIN can access path /foo/something
.requestMatchers("/bar/*", "/baz/*").hasRole("ADMIN") // only authenticated requests to paths /foo/something and /baz/something  are allowed
Run Code Online (Sandbox Code Playgroud)
  • requestMatchers( HttpMethod )- 需要一个HttpMethodas 参数。相应的限制(hasRole()access()等)将应用于当前SecurityFilterChain指定 HttpMethod 处理的任何请求。如果null作为参数提供,任何请求都会匹配。

例子:

.requestMatchers(HttpMethod.POST, "/bar/**").hasAnyRole("USER", "ADMIN") // any authenticated POST-requests should from an ADMIN or USER are allowed
Run Code Online (Sandbox Code Playgroud)

例子:

.requestMatchers(HttpMethod.POST, "/bar/**").hasAnyRole("USER", "ADMIN") // any POST-request should be authenticatd
.requestMatchers(HttpMethod.DELETE, "/baz/**").hasRole( "ADMIN") // only ADMINs can issue DELETE-requests to these paths
Run Code Online (Sandbox Code Playgroud)
  • requestMatchers( RequestMatcher ... )- 最后一个版本可能是最灵活的版本,它允许提供任意数量的组合RequestMatcher实例。我们不需要自己实现这个接口(除非有特殊需要),有几种开箱即用的实现包括RegexRequestMatcher(可用于替换过时的regexMatchers())。

例子:

.requestMatchers(new RegexRequestMatcher("/foo/bar", "POST")).authenticated()
Run Code Online (Sandbox Code Playgroud)

示例 - 解决原始问题

我想POST只允许对路径的请求"/api/subscription"

为此,我们需要使用这种风格,requestMatchers(HttpMethod, String...)它允许为 path 指定 HTTP 方法和模式"/api/subscription"

提醒: WebSecurityConfigureAdapter自 Spring Security发布以来已被弃用5.7,现在HttpSecurity正在配置SecurityFilterChain,应将其定义为 Bean。

以下是我们如何使用 Spring 6 和 lambda DSL 保护对问题中定义的路径的请求:

.requestMatchers("/foo/*").hasRole("ADMIN") // only authenticated user with role ADMIN can access path /foo/something
.requestMatchers("/bar/*", "/baz/*").hasRole("ADMIN") // only authenticated requests to paths /foo/something and /baz/something  are allowed
Run Code Online (Sandbox Code Playgroud)

笔记

  • 正在从上到下评估安全规则,将应用第一个匹配的规则。确保以正确的顺序声明规则。

  • 应用默认拒绝策略。随着应用程序的发展,会引入新的路径,并且在这些更改期间,您的同事可能会忘记更新安全限制,并且某些端点似乎不受保护。为了避免在每个过滤器链中SecurityFilterChain我们可以声明多个过滤器链,以配置系统的不同部分并指定它们的顺序SecurityFilterChain)作为最后一个约束,您可以引入一个匹配器,该匹配器包含受此约束的所有未指定的 URL "/foo/**"(即下的所有路径) /foo) 应用authenticated()denyAll()。并且SecurityFilterChain被认为是最后一个处理请求的应该从根目录中删除对所有未指定 URL 的请求requestMatchers("/**").denyAll()。该配置将防止未经身份验证的访问并泄露系统中有效的路径。如果新引入的端点不可访问(例如,应允许非授权请求),那么在开发过程中对您的同事来说将是显而易见的。指定应该打开的内容并默认关闭其他所有内容会更安全。

Spring 5.7 及更早版本

正如我一开始所说的,即使使用 Spring 版本antMatchers(),因为通过使用它们,您最终可能会导致访问控制有效性损坏。

这是另一个相关链接:弃用尾随斜杠匹配

相反,请考虑应用mvcMathcers()顾名思义使用 Spring MVC 匹配规则或基于正则表达式的regexMatchers(). 和mvcMathcers()都有regexMatchers()一个允许指定 HTTP 方法的重载版本。

mvcMathcers()下面是如何使用Spring Security 5.2 Lambda DSL来保护 API 免受问题的影响:

@Configuration
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain securityFilterChain1(HttpSecurity http) {
        
        return http
            // other configuration options
            .authorizeRequests(authCustomizer -> authCustomizer
                .mvcMatchers(
                    "/api/register", "/api/register", "/api/authenticate"
                ).permitAll()
                .mvcMatchers("/api/logs/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .mvcMatchers(HttpMethod.POST, "/api/subscriptions").permitAll()
                .mvcMatchers("/api/**").authenticated()
                .regexMatchers("/**").denyAll()
            )
            .build();
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我知道这个问题有点老了,但是我不认为禁用csrf支持是可以接受的答案。我遇到了同样的问题,但使用csrf.disable()感到不舒服。相反,我在页面底部的表单标签内添加了以下行。

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Run Code Online (Sandbox Code Playgroud)