SpringSecurity中文文档(Servlet Authorize HttpServletRequests)

Authorize HttpServletRequests

SpringSecurity 允许您在请求级别对授权进行建模。例如,对于 Spring Security,可以说/admin 下的所有页面都需要一个权限,而其他所有页面只需要身份验证。

默认情况下,SpringSecurity 要求对每个请求进行身份验证。也就是说,任何时候使用 HttpSecurity 实例,都需要声明授权规则。

无论何时有 HttpSecurity 实例,您至少应该这样做:

Use authorizeHttpRequests

http
    .authorizeHttpRequests((authorize) -> authorize
        .anyRequest().authenticated()
    )

这告诉 Spring Security,应用程序中的任何端点都需要至少对安全上下文进行身份验证才能允许它。

在许多情况下,您的授权规则将比这更复杂,因此请考虑以下用例:

  • 我有一个使用 AuthorizeRequest 的应用程序,我想将它迁移到 AuthorizeHttpRequest(I have an app that uses authorizeRequests and I want to migrate it to authorizeHttpRequests)
  • 我想了解 AuthorizationFilter 组件是如何工作的(I want to understand how the AuthorizationFilter components work)
  • 我希望根据模式匹配请求,特别是正则表达式(I want to match requests based on a pattern; specifically regex)
  • 我想匹配请求,并将 SpringMVC 映射到默认 servlet 之外的其他内容(I want to match request, and I map Spring MVC to something other than the default servlet)
  • I want to authorize requests
  • 希望以编程方式匹配请求(I want to match a request programmatically)
  • 我想以编程方式授权一个请求(I want to authorize a request programmatically)
  • 我要将请求授权委托给策略代理(I want to delegate request authorization to a policy agent)

Understanding How Request Authorization Components Work

本节通过深入研究基于 Servlet 的应用程序中的请求级授权如何工作,构建在 Servlet 体系结构和实现的基础上。

authorizationfilter

  • number 1 首先,AuthorizationFilter 构建了一个 Supplier,用于从 SecurityContextHolder 检索 Authentication。(First, the AuthorizationFilter constructs a Supplier that retrieves an Authentication from the SecurityContextHolder.)
  • number 2 第二,它将 Supplier 和 HttpServletRequest 传递给 AuthorizationManager。AuthorizationManager 将请求与 authorizeHttpRequests 中的模式进行匹配,并运行相应的规则。
    • number 3 如果授权被拒绝,将发布一个 AuthorizationDeniedEvent,并抛出一个 AccessDeniedException。在这种情况下,ExceptionTranslationFilter 将处理 AccessDeniedException。
    • number 4如果授予访问权限,则发布 AuthorizationGrantedEvent,AuthorizationFilter 继续使用 FilterChain,它允许应用程序正常处理。

AuthorizationFilter Is Last By Default

AuthorizationFilter 默认是 Spring Security 过滤器链中的最后一个。这意味着 Spring Security 的认证过滤器、漏洞保护以及其他过滤器集成不需要授权。如果您在 AuthorizationFilter 之前添加自己的过滤器,它们也不需要授权;否则,它们将需要授权。

一个典型的场景是当您添加 Spring MVC 端点时。因为它们由 DispatcherServlet 执行,这发生在 AuthorizationFilter 之后,所以您的端点需要被包含在 authorizeHttpRequests 中才能被允许。

All Dispatches Are Authorized

AuthorizationFilter 不仅在每次请求时运行,而且在每次分发时都会运行。这意味着 REQUEST 分发需要授权,但 FORWARD、ERROR 和 INCLUDE 也是如此。

例如,Spring MVC 可以将请求转发到呈现 Thymeleaf 模板的视图解析器,如下所示:

@Controller
public class MyController {
    @GetMapping("/endpoint")
    public String endpoint() {
        return "endpoint";
    }
}

在这种情况下,授权发生两次; 一次用于授权/端点,一次用于转发到 Thymeleaf 以呈现“端点”模板。

因此,您可能希望允许所有 FORWARD 分派。

这个原则的另一个例子是 SpringBoot 如何处理错误。如果容器捕获到异常,则如下所示:

Sample Erroring Spring MVC Controller

@Controller
public class MyController {
    @GetMapping("/endpoint")
    public String endpoint() {
        throw new UnsupportedOperationException("unsupported");
    }
}

然后 Boot 会将其发送到 ERROR 调度。

在这种情况下,授权也会发生两次: 一次用于授权/端点,一次用于分派错误。

因此,您可能希望允许所有 ERROR 分派。

Authentication Lookup is Deferred

记住 AuthorizationManager API 使用 Supplier < Authentication > 。

当请求总是被允许或总是被拒绝时,这与 AuthorizeHttpRequest 有关。在这些情况下,不会查询身份验证,从而使请求速度更快。

Authorizing an Endpoint

通过在优先顺序中添加更多规则,可以将 Spring Security 配置为具有不同的规则。

如果您希望只有具有 USER 权限的最终用户才能访问该/端点,那么您可以这样做:

@Bean
public SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
	    .requestMatchers("/endpoint").hasAuthority("USER")
            .anyRequest().authenticated()
        )
        // ...

    return http.build();
}

如您所见,声明可以分解为pattern/rule对。

AuthorizationFilter 按列出的顺序处理这些对,只将第一个匹配应用到请求上。这意味着,即使 /** 也会匹配 /endpoint,上述规则也不是问题。阅读上述规则的方式是:“如果请求是 /endpoint,则需要 USER 权限;否则,只需认证”。

SpringSecurity 支持多种模式和多种规则; 您还可以通过编程方式创建自己的模式和规则。

一旦授权,您可以使用 Security 的测试支持以下方式对其进行测试:

Test Endpoint Authorization

@WithMockUser(authorities="USER")
@Test
void endpointWhenUserAuthorityThenAuthorized() {
    this.mvc.perform(get("/endpoint"))
        .andExpect(status().isOk());
}

@WithMockUser
@Test
void endpointWhenNotUserAuthorityThenForbidden() {
    this.mvc.perform(get("/endpoint"))
        .andExpect(status().isForbidden());
}

@Test
void anyWhenUnauthenticatedThenUnauthorized() {
    this.mvc.perform(get("/any"))
        .andExpect(status().isUnauthorized());
}

Matching Requests

上面已经介绍了两种匹配请求的方法。

您看到的第一个是最简单的,即匹配任何请求。

第二种是通过 URI 模式进行匹配。Spring Security 支持两种用于 URI 模式匹配的语言: Ant (如上所示)和正则表达式。

Matching Using Ant

Ant 是 Spring Security 用来匹配请求的默认语言。

您可以使用它来匹配单个端点或目录,甚至可以捕获占位符以供以后使用。您还可以对其进行细化以匹配一组特定的 HTTP 方法。

假设您不希望匹配/endpoint 端点,而是希望匹配/resource 目录下的所有端点。在这种情况下,您可以执行以下操作:

Match with Ant

http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers("/resource/**").hasAuthority("USER")
        .anyRequest().authenticated()
    )

解读方法是“如果请求是/resource 或某个子目录,则需要 USER 权限; 否则,只需要身份验证”

您还可以从请求中提取路径值,如下所示:

Authorize and Extract

http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers("/resource/{name}").access(new WebExpressionAuthorizationManager("#name == authentication.name"))
        .anyRequest().authenticated()
    )

一旦授权,您可以使用 Security 的测试支持以下方式对其进行测试:

Test Directory Authorization

@WithMockUser(authorities="USER")
@Test
void endpointWhenUserAuthorityThenAuthorized() {
    this.mvc.perform(get("/endpoint/jon"))
        .andExpect(status().isOk());
}

@WithMockUser
@Test
void endpointWhenNotUserAuthorityThenForbidden() {
    this.mvc.perform(get("/endpoint/jon"))
        .andExpect(status().isForbidden());
}

@Test
void anyWhenUnauthenticatedThenUnauthorized() {
    this.mvc.perform(get("/any"))
        .andExpect(status().isUnauthorized());
}

SpringSecurity 只匹配路径。如果要匹配查询参数,则需要一个自定义请求匹配器。

Matching Using Regular Expressions

SpringSecurity 支持将请求与正则表达式匹配。如果您想在子目录上应用比 * * 更严格的匹配条件,这可能很方便。

例如,考虑一个包含用户名的路径和所有用户名必须是字母数字的规则。您可以使用 RegexRequestMatcher 来遵守此规则,如下所示:

http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(RegexRequestMatcher.regexMatcher("/resource/[A-Za-z0-9]+")).hasAuthority("USER")
        .anyRequest().denyAll()
    )

Matching By Http Method

还可以通过 HTTP 方法匹配规则。有一个地方很方便,那就是通过授予的权限进行授权,比如授予读或写权限。

为了要求所有 GET 都具有读权限,并且所有 POST 都具有写权限,您可以这样做:

Match by HTTP Method

http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(HttpMethod.GET).hasAuthority("read")
        .requestMatchers(HttpMethod.POST).hasAuthority("write")
        .anyRequest().denyAll()
    )

这些授权规则的内容应该是: “如果请求是 GET,则需要读权限; 否则,如果请求是 POST,则需要写权限; 否则,拒绝请求”

默认情况下拒绝请求是一种健康的安全实践,因为它将规则集转换为允许列表。

一旦授权,您可以使用 Security 的测试支持以下方式对其进行测试:

Test Http Method Authorization

@WithMockUser(authorities="read")
@Test
void getWhenReadAuthorityThenAuthorized() {
    this.mvc.perform(get("/any"))
        .andExpect(status().isOk());
}

@WithMockUser
@Test
void getWhenNoReadAuthorityThenForbidden() {
    this.mvc.perform(get("/any"))
        .andExpect(status().isForbidden());
}

@WithMockUser(authorities="write")
@Test
void postWhenWriteAuthorityThenAuthorized() {
    this.mvc.perform(post("/any").with(csrf()))
        .andExpect(status().isOk());
}

@WithMockUser(authorities="read")
@Test
void postWhenNoWriteAuthorityThenForbidden() {
    this.mvc.perform(get("/any").with(csrf()))
        .andExpect(status().isForbidden());
}

Matching By Dispatcher Type

XML 当前不支持此特性

如前所述,SpringSecurity 默认授权所有调度程序类型。而且,即使在 REQUEST 分派上建立的安全上下文将传递给后续分派,微妙的不匹配有时也会导致意外的 AccessDeniedException。

为了解决这个问题,您可以配置 Spring Security Java 配置,以允许 FORWARD 和 ERROR 等调度程序类型,如下所示:

http
    .authorizeHttpRequests((authorize) -> authorize
        .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
        .requestMatchers("/endpoint").permitAll()
        .anyRequest().denyAll()
    )

Using an MvcRequestMatcher

一般来说,可以像上面演示的那样使用 requestMatcher (String)。

但是,如果将 SpringMVC 映射到不同的 servlet 路径,则需要在安全配置中考虑这一点。

例如,如果 Spring MVC 被映射到/Spring-MVC 而不是/(默认值) ,那么您可能有一个想要授权的端点,比如/Spring-MVC/my/controller。

您需要使用 MvcRequestMatcher 在配置中分割 servlet 路径和控制器路径,如下所示:

Example 2. Match by MvcRequestMatcher

@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
	return new MvcRequestMatcher.Builder(introspector).servletPath("/spring-mvc");
}

@Bean
SecurityFilterChain appEndpoints(HttpSecurity http, MvcRequestMatcher.Builder mvc) {
	http
        .authorizeHttpRequests((authorize) -> authorize
            .requestMatchers(mvc.pattern("/my/controller/**")).hasAuthority("controller")
            .anyRequest().authenticated()
        );

	return http.build();
}

这种需要至少可以通过两种不同的方式产生:

  • 如果使用 spring.mvc.servlet.path Boot 属性将默认路径(/)更改为其他内容
  • 如果您注册了多个 Spring MVC DispatcherServlet (因此要求其中一个不是默认路径)

Using a Custom Matcher

XML 当前不支持此特性

在 Java 配置中,您可以创建自己的 RequestMatcher 并将其提供给 DSL,如下所示:

Example 3. Authorize by Dispatcher Type

RequestMatcher printview = (request) -> request.getParameter("print") != null;
http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(printview).hasAuthority("print")
        .anyRequest().authenticated()
    )

一旦授权,您可以使用 Security 的测试支持以下方式对其进行测试:

@WithMockUser(authorities="print")
@Test
void printWhenPrintAuthorityThenAuthorized() {
    this.mvc.perform(get("/any?print"))
        .andExpect(status().isOk());
}

@WithMockUser
@Test
void printWhenNoPrintAuthorityThenForbidden() {
    this.mvc.perform(get("/any?print"))
        .andExpect(status().isForbidden());
}

Authorizing Requests

一旦匹配了一个请求,您可以通过几种方式对其进行授权,如 permitAll、 denyAll 和 hasAuthority。

作为一个快速总结,以下是 DSL 中内置的授权规则:

  • PermitAll-请求不需要授权,是一个公共端点; 请注意,在这种情况下,永远不会从会话检索 Authentication
  • DenyAll-在任何情况下都不允许请求; 请注意,在这种情况下,永远不会从会话检索 Authentication
  • HasAuthority ——该请求要求 Authentication 具有与给定值匹配的 GrantedAuthority
  • HasRole-hasAuthority 的一个快捷方式,它将 ROLE _ 或其他配置为默认前缀的内容作为前缀
  • HasAnyAuthority ——该请求要求 Authentication 具有与任何给定值匹配的 GrantedAuthority
  • HasAnyrole-hasAnyAuthority 的一个快捷方式,它将 ROLE _ 或任何被配置为默认前缀的东西作为前缀
  • Access-请求使用此自定义 AuthorizationManager 来确定访问权限

现在已经了解了模式、规则以及如何将它们配对在一起,您应该能够理解在这个更复杂的示例中发生了什么:

import static jakarta.servlet.DispatcherType.*;

import static org.springframework.security.authorization.AuthorizationManagers.allOf;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasRole;

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize                                  (1)
            .dispatcherTypeMatchers(FORWARD, ERROR).permitAll() (2)
			.requestMatchers("/static/**", "/signup", "/about").permitAll()         (3)
			.requestMatchers("/admin/**").hasRole("ADMIN")                             (4)
			.requestMatchers("/db/**").access(allOf(hasAuthority("db"), hasRole("ADMIN")))   (5)
			.anyRequest().denyAll()                                                (6)
		);

	return http.build();
}
  1. 指定了多个授权规则。每个规则按其声明的顺序进行考虑。
  2. 分派 FORWARD 和 ERROR 允许 Spring MVC 呈现视图,Spring Boot 呈现错误
  3. 我们指定了任何用户都可以访问的多个 URL 模式。具体来说,如果 URL 以“/static/”、等于“/signup”或等于“/about”开头,则任何用户都可以访问请求。
  4. 任何以“/admin/”开头的 URL 将仅限于具有“ ROLE _ ADMIN”角色的用户。您会注意到,由于我们正在调用 hasRole 方法,因此不需要指定“ ROLE _”前缀。
  5. 任何以 “/db/” 开头的 URL 都需要用户同时拥有 “db” 权限以及 “ROLE_ADMIN” 角色。您会注意到,由于我们使用了 hasRole 表达式,因此不需要指定 “ROLE_” 前缀。
  6. 任何尚未匹配的 URL 都将被拒绝访问。如果您不想意外地忘记更新授权规则,那么这是一个很好的策略。

Expressing Authorization with SpEL

虽然建议使用具体的 AuthorizationManager,但是在某些情况下需要使用表达式,比如使用 < stop-url > 或 JSP Taglibs。出于这个原因,本节将重点介绍来自这些域的示例。

既然如此,让我们更深入地讨论一下 Spring Security 的 Web 安全授权 SpEL API。

Spring Security 将其所有的授权字段和方法封装在一个集合的根对象中。最通用的根对象称为 SecurityExpressionRoot,它是 WebSecurityExpressionRoot 的基础。当准备评估授权表达式时,Spring Security 将这个根对象提供给 StandardEvaluationContext。

Using Authorization Expression Fields and Methods

它提供的第一件事是增强了 SpEL 表达式的授权字段和方法集。以下是最常用方法的简要概述:

  • permitAll - 请求不需要任何授权即可调用;注意,在这种情况下,Authentication 从未从会话中检索

  • denyAll - 请求在任何情况下都不被允许;注意,在这种情况下,Authentication 从未从会话中检索

  • hasAuthority - 请求需要 Authentication 具有与给定值匹配的 GrantedAuthority

  • hasRole - hasAuthority 的快捷方式,默认前缀为 ROLE_ 或配置的默认前缀

  • hasAnyAuthority - 请求需要 Authentication 具有与给定值中的任何一个匹配的 GrantedAuthority

  • hasAnyRole - hasAnyAuthority 的快捷方式,默认前缀为 ROLE_ 或配置的默认前缀

  • HasPermission-一个连接到您的 Permisonevalator 实例的钩子,用于执行对象级授权

以下是一些最常见的领域:

  • authentication - 与本方法调用相关联的 Authentication 实例

  • principal - 与本方法调用相关联的 Authentication#getPrincipal

现在已经了解了模式、规则以及如何将它们配对在一起,您应该能够理解在这个更复杂的示例中发生了什么:

Authorize Requests Using SpEL

<http>
    <intercept-url pattern="/static/**" access="permitAll"/>1<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>2<intercept-url pattern="/db/**" access="hasAuthority('db') and hasRole('ADMIN')"/>3<intercept-url pattern="/**" access="denyAll"/>4</http>
  1. 我们指定了一个任何用户都可以访问的 URL 模式。具体来说,如果 URL 以“/static/”开头,任何用户都可以访问请求。
  2. 任何以“/admin/”开头的 URL 将仅限于具有“ ROLE _ ADMIN”角色的用户。您会注意到,由于我们正在调用 hasRole 方法,因此不需要指定“ ROLE _”前缀。
  3. 任何以 “/db/” 开头的 URL 都需要用户同时拥有 “db” 权限以及 “ROLE_ADMIN” 角色。您会注意到,由于我们使用了 hasRole 表达式,因此不需要指定 “ROLE_” 前缀。
  4. 任何尚未匹配的 URL 都将被拒绝访问。如果您不想意外地忘记更新授权规则,那么这是一个很好的策略。

Using Path Parameters

此外,Spring Security 提供了一种发现路径参数的机制,因此也可以在 SpEL 表达式中访问这些参数。

例如,您可以通过以下方式访问 SpEL 表达式中的路径参数:

Authorize Request using SpEL path variable

<http>
    <intercept-url pattern="/resource/{name}" access="#name == authentication.name"/>
    <intercept-url pattern="/**" access="authenticated"/>
</http>

这个表达式引用/resource/之后的 path 变量,并要求它等于 Authentication # getName。

Use an Authorization Database, Policy Agent, or Other Service

如果希望将 Spring Security 配置为使用单独的服务进行授权,可以创建自己的 AuthorizationManager 并将其与 anyRequest 匹配。

首先,您的 AuthorizationManager 可能看起来像这样:

Open Policy Agent Authorization Manager

@Component
public final class OpenPolicyAgentAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
        // make request to Open Policy Agent
    }
}

然后,您可以通过以下方式将其连接到 Spring Security:

Any Request Goes to Remote Service

@Bean
SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> authz) throws Exception {
	http
		// ...
		.authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(authz)
		);

	return http.build();
}

Favor permitAll over ignoring

当您拥有静态资源时,很容易将筛选器链配置为忽略这些值。一个更安全的方法是允许他们使用 permitAll like so:

Example 4. Permit Static Resources

http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers("/css/**").permitAll()
        .anyRequest().authenticated()
    )

它更加安全,因为即使使用静态资源,编写安全头文件也很重要,如果忽略请求,Spring Security 就无法做到这一点。

在过去,这带来了性能折衷,因为 Spring Security 在每次请求时都会咨询会话。但是,从 SpringSecurity6开始,除非授权规则要求,否则不再 ping 会话。由于现在已经解决了性能影响问题,SpringSecurity 建议对所有请求至少使用 permitAll。

Migrating from authorizeRequests

AuthorizationFilter 为 HttpServletRequest 提供授权。它作为安全筛选器之一插入到 FilterChainProxy 中。

您可以在声明 SecurityFilterChain 时覆盖默认值:

@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated();
        )
        // ...

    return http.build();
}

这在若干方面改进了 AuthorizeRequest:

  • 使用简化的 AuthorizationManager API 而不是元数据源、配置属性、决策管理器和投票者metadata sources, config attributes, decision managers, and voters.。这简化了重用和自定义。
  • 延迟 Authentication 查找。而不是为每个请求都查找 Authentication,只有在需要授权决策时才会查找。
  • 支持基于 Bean 的配置。

如果使用 AuthorizeHttpRequest 代替 AuthorizeRequest,则使用 AuthorizationFilter 代替 FilterSecurityInterceptor。

Migrating Expressions

在可能的情况下,建议使用类型安全授权管理器而不是 SpEL。对于 Java 配置,WebExpressionAuthorizationManager 可用于帮助迁移遗留的 SpEL。

要使用 WebExpressionAuthorizationManager,您可以使用试图迁移的表达式构造一个表达式,如下所示:

.requestMatchers("/test/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') && hasRole('USER')"))

如果您在表达式中引用一个 bean,例如:@webSecurity.check(authentication, request),建议您直接调用 bean,它看起来会像这样:

.requestMatchers("/test/**").access((authentication, context) ->
    new AuthorizationDecision(webSecurity.check(authentication.get(), context.getRequest())))

对于包含 bean 引用和其他表达式的复杂指令,建议更改这些指令以实现 AuthorizationManager,并通过调用.access(AuthorizationManager).

如果不能这样做,可以使用 bean 解析器配置 DefaultHttpSecurityExpressionHandler,并将其提供给 WebExpressionAuthorizationManager # setExpressionHandler。

Security Matchers

RequestMatcher 接口用于确定请求是否与给定的规则匹配。我们使用 securityMatchers 来确定给定的 HttpSecurity 是否应该应用于给定的请求。同样,我们可以使用 requestMatchers 来确定应该应用于给定请求的授权规则。请看以下示例:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher("/api/**")
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers("/user/**").hasRole("USER")
				.requestMatchers("/admin/**").hasRole("ADMIN")
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}
  1. 将 HttpSecurity 配置为仅应用于以/api/开头的 URL
  2. 允许具有 USER 角色的用户访问以 /user/ 开头的 URL
  3. 允许具有 ADMIN 角色的用户访问以/admin/开头的 URL
  4. 任何其他与上述规则不匹配的请求都将需要身份验证

SecurityMatcher (s)和 requestMatcher (s)方法将决定哪个 RequestMatcher 实现最适合您的应用程序: 如果 Spring MVC 在类路径中,那么将使用 MvcRequestMatcher,否则将使用 AntPathRequestMatcher。您可以在这里了解更多关于 Spring MVC 集成的信息。

如果您想使用一个特定的 RequestMatcher,只需将一个实现传递给 securityMatcher 和/或 requestMatcher 方法:

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; (1)
import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
		http
			.securityMatcher(antMatcher("/api/**"))                              (2)
			.authorizeHttpRequests(authorize -> authorize
				.requestMatchers(antMatcher("/user/**")).hasRole("USER")         (3)
				.requestMatchers(regexMatcher("/admin/.*")).hasRole("ADMIN")     (4)
				.requestMatchers(new MyCustomRequestMatcher()).hasRole("SUPERVISOR")     (5)
				.anyRequest().authenticated()
			)
			.formLogin(withDefaults());
		return http.build();
	}
}

public class MyCustomRequestMatcher implements RequestMatcher {

    @Override
    public boolean matches(HttpServletRequest request) {
        // ...
    }
}
  1. 从 AntPathRequestMatcher 和 RegexRequestMatcher 导入静态工厂方法以创建 RequestMatcher 实例。
  2. 使用 AntPathRequestMatcher 将 HttpSecurity 配置为仅应用于以/api/开头的 URL
  3. 允许使用 AntPathRequestMatcher 访问以/USER/开头的 URL 到具有 USER 角色的用户
  4. 允许使用 RegexRequestMatcher 对具有 ADMIN 角色的用户访问以/ADMIN/开头的 URL
  5. 允许使用自定义 RequestMatcher 访问与具有 SUPERVISOR 角色的用户匹配的 MyCustomRequestMatcher 的 URL

Further Reading

既然已经保护了应用程序的请求,那么就考虑保护它的方法。您还可以进一步阅读关于测试应用程序或将 Spring Security 与应用程序的其他方面(如数据层或跟踪和度量)集成的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/792598.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6、Redis系统-数据结构-04-Hash

四、哈希表&#xff08;Hashtable&#xff09; 哈希表是一种高效的键值对数据结构&#xff0c;通过散列函数将键映射到表中的位置&#xff0c;实现快速的插入、删除和查找操作。Redis 广泛使用哈希表来实现 Hash 对象和数据库的键值存储。以下将从结构设计、哈希冲突与链式哈希…

快速测试electron环境是否安装成功

快速测试electron环境是否安装成功 测试代码正确运行的效果运行错误的效果v22.4.1 版本无法使用v20.15.1版本无法使用v18.20.4 版本无法使用 终极解决办法 测试代码 1.npx create-electron-app my-electron-app 2.cd my-electron-app 3.npm start 正确运行的效果 环境没问题…

Android系统设置kernel log level的方法

Android log相关文档索引&#xff1a; 使用ADB命令控制logcat日志本地存储功能-CSDN博客 Android系统通过属性设置来控制log输出的方案-CSDN博客 Android系统设置kernel log level的方法-CSDN博客 Android系统设置kernel log level的方法 背景 kernel log内容过多/过少会影…

oak相机使用oak官网方式标定

目录 一、depthai ROS驱动 一、depthai ROS驱动 &#xff08;1&#xff09;驱动下载地址&#xff1a;2. C 开发快速上手 — DepthAI Docs 0.3.0.0 documentation sudo apt install ./depthai_2.17.1_arm64.deb //运行 Python3 utilities/cam_test.py -mres 400 -cams rgb,m …

Wireshark 对 https 请求抓包并展示为明文

文章目录 1、目标2、环境准备3、Wireshark 基本使用4、操作步骤4.1、彻底关闭 Chrome 进程4.2、配置 SSLKEYLOGFILE [核心步骤]4.3、把文件路径配置到 Wireshark 指定位置4.4、在浏览器发起请求4.5、抓包配置4.6、过滤4.6.1、过滤域名 http.host contains "baidu.com4.6.2…

AIGC时代创意设计师从“创作”向“智作”升级

随着人工智能技术的飞速发展&#xff0c;AIGC&#xff08;AI Generated Content&#xff0c;即人工智能生成内容&#xff09;时代已经到来&#xff0c;为创意设计领域带来了前所未有的变革。在这一时代背景下&#xff0c;创意设计师们正经历着从传统的“创作”向“智作”的转型…

FreeRTOS 队列

队列是一种任务到任务、任务到中断、中断到任务数据交流的一种机制。在队列中可以存 储数量有限、大小固定的多个数据&#xff0c;队列中的每一个数据叫做队列项目&#xff0c;队列能够存储队列项 目的最大数量称为队列的长度&#xff0c;在创建队列的时候&#xff0c;就需要指…

html5——CSS基础选择器

目录 标签选择器 类选择器 id选择器 三种选择器优先级 标签指定式选择器 包含选择器 群组选择器 通配符选择器 Emmet语法&#xff08;扩展补充&#xff09; 标签选择器 HTML标签作为标签选择器的名称&#xff1a; <h1>…<h6>、<p>、<img/> 语…

在pycharm中使用jupyter

在pycharm中使用jupyter 前置条件&#xff1a;你的环境中应该有juptyer &#xff0c;没有的话 pip install jupyter 点击项目目录&#xff0c;右键->new->jupyter notebook 打开file settings 找到 jupyter server &#xff08;按照默认的用代理服务器就行&#xff09; P…

ollama + lobechat 搭建自己的多模型助手

背景 人工智能已经推出了快2年了&#xff0c;各种模型和插件&#xff0c;有渐渐变成熟的趋势&#xff0c;打造一个类似 hao123网站的人工智能模型入口&#xff0c;也变得有需求了。用户会去比较多个ai给出的答案&#xff0c;作为程序员想拥有一台自己的GPU服务器来为自己服务。…

react启用mobx @decorators装饰器语法

react如果没有经过配置&#xff0c;直接使用decorators装饰器语法会报错&#xff1a; Support for the experimental syntax ‘decorators’ isn’t currently enabled 因为react默认是不支持装饰器语法&#xff0c;需要做一些配置来启用装饰器语法。 step1: 在 tsconfig.js…

always块敏感列表的相关报错,

在综合的时候&#xff0c;报错如下 Synthesis synth_1 [Synth 8-91] ambiguous clock in event control ["E:/FPGA/FPGA_project/handwrite_fft/handwrite_fft.srcs/sources_1/new/reg_s2p.v":140] 猜测报错原因&#xff08;暂时没有时间寻找原因&#xff0c;后续在…

【linux】服务器卸载cuda

【linux】服务器卸载cuda 文章目录 【linux】服务器卸载cuda1、查找已安装的 CUDA 包&#xff1a;2、卸载 CUDA&#xff1a;3、删除残留文件4、更新系统的包索引&#xff1a;5、检查是否卸载干净&#xff1a; 1、查找已安装的 CUDA 包&#xff1a; dpkg -l | grep cuda2、卸载…

Unity之OpenXR+XR Interaction Toolkit实现 Gaze眼部追踪

使用 Unity OpenXR 实现Gaze眼部追踪 在虚拟现实(VR)和增强现实(AR)应用中,眼动追踪是一项强大而受欢迎的技术。它可以让开发者更好地理解用户的注意力和行为,并创造出更加沉浸和智能的体验。在本文中,我们将探讨如何使用 Unity OpenXR 实现Gaze眼部追踪功能。 Unity …

IEEE顶刊“放水”?稳居1区Top,发文扩张IF稳长,CCF推荐,审稿友好!

本周投稿推荐 SCI • 能源科学类&#xff0c;1.5-2.0&#xff08;25天来稿即录&#xff09; • CCF推荐&#xff0c;4.5-5.0&#xff08;2天见刊&#xff09; • 生物医学制药类&#xff08;2天逢投必中&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09…

python3读取shp数据

目录 1 介绍 1 介绍 需要tmp.shp文件和tmp.dbf文件&#xff0c;需要安装geopandas第三方库&#xff0c;python3代码如下&#xff0c; import geopandas as gpdshp_file_path "tmp.shp" shp_data gpd.read_file(shp_file_path) for index, row in shp_data.iterro…

【Neo4j】实战 (数据库技术丛书)学习笔记

Neo4j实战 (数据库技术丛书) 第1章演示了应用Neo4j作为图形数据库对改进性能和扩展性的可能性, 也讨论了对图形建模的数据如何正好适应于Neo4j数据模型,现在到了该动 手实践的时间了。第一章 概述 Neo4j将数据作为顶点和边存储(或者用Neo4j术语,节点和关系存 储)。用户被定…

DSC主备归档报错

先看一个报错&#xff1a; 2024-07-10 22:12:21.725 [ERROR] database P0000003511 T0000000000000003696 rafil_list_overlap_consecutive_check failed, rfil(DMDATA/data/DSC02/arch/ARCHIVE_LOCAL1_0x57843343_EP1_2024-07-10_20-44-40.log)->next_seq(2901) > nex…

2.54插座开口朝板内还是板外?

答&#xff1a;开口朝板内。 这样无论是安装立式插座&#xff0c;还是卧式插座&#xff0c;引脚定义都一致。并且从左往右&#xff1a;1,2,3,4

Nordic 蓝牙5产品简介

蓝牙5.0 有四个重要的新功能&#xff1a; 更高的比特率为 2 Mbps。长距离模式在 500 kbps 和 125 kbps 两个新的较低比特率下具有更好的灵敏度。通过广告扩展&#xff0c;广播能力提高了 8 倍。改进的信道选择算法 (CSA #2)&#xff0c;可以提高与其他蓝牙和非蓝牙流量的信道协…