Spring Security AuthorizationManager – Spring Security AuthorizationManager

最后修改: 2024年 3月 11日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.导言

Spring Security is an extension of the Spring Framework that makes it easy to build common security practices into our applications. This includes things like user authentication and authorization, API protection, and much more.

Spring安全Spring框架的扩展,它使我们能够轻松地在应用程序中构建常见的安全实践。这包括用户身份验证和授权、API 保护等内容。

In this tutorial, we look at one of the many pieces inside Spring Security: the AuthorizationManager. We’ll see how it fits into the larger Spring Security ecosystem, as well as various use cases for how it can help secure our applications.

在本教程中,我们将了解 Spring Security 的众多组件之一:AuthorizationManager。我们将了解它如何融入更大的 Spring Security 生态系统,以及它如何帮助确保应用程序安全的各种用例。

2. What Is Spring Security AuthorizationManager

2.什么是 Spring Security AuthorizationManager?

The Spring AuthorizationManager is an interface that allows us to check if an authenticated entity has access to a secured resource. AuthorizationManager instances are used by Spring Security to make final access control decisions for request-based, method-based, and message-based components.

SpringAuthorizationManager是一个接口,它允许我们检查经过验证的实体是否可以访问安全资源。AuthorizationManager实例被 Spring Security 用于为基于请求、基于方法和基于消息的组件做出最终访问控制决策。

As background, Spring Security has a few key concepts that are helpful to understand before looking at the specific role of the AuthorizationManager:

作为背景知识,在了解 AuthorizationManager 的具体作用之前,了解 Spring Security 的一些关键概念很有帮助:

  • Entity: anything that can make a request into the system. This could be a human user or a remote web service, for example.
  • Authentication: the process of verifying that an entity is who they say they are. This can be via username/password, token, or any number of other methods.
  • Authorization: the process of verifying an entity has access to a resource
  • Resource: any information the system makes available for access — for example, a URL or document
  • Authority: often referred to as a Role, this is a logical name representing the permissions an entity has. A single entity may have zero or more authorities granted to it.

With these concepts in mind, we can dive deeper into the AuthorizationManager interface.

有了这些概念,我们就可以深入研究 AuthorizationManager 接口。

2.1. How to Use AuthorizationManager

2.1.如何使用授权管理器</em

AuthorizationManager is a simple interface that contains only two methods:

AuthorizationManager 是一个简单的接口,只包含两个方法:

AuthorizationDecision check(Supplier<Authentication> authentication, T object);

void verify(Supplier<Authentication> authentication, T object);

Both methods look similar because they take the same arguments:

这两种方法看起来很相似,因为它们使用相同的参数:

  • authentication: a Supplier that provides an Authentication object representing the entity making the request.
  • object: the secure object being requested (will vary depending on the nature of the request)

However, each method serves a different purpose. The first method returns an AuthorizationDecision, which is a simple wrapper around a boolean value that indicates whether or not the entity can access the secure object.

但是,每个方法都有不同的用途。第一个方法返回一个 AuthorizationDecision 方法,它是对一个 boolean 值的简单封装,表示实体是否可以访问安全对象。

The second method doesn’t return anything. Instead, it simply performs the authorization check and throws an AccessDeniedException if the entity is not authorized to access the secure object.

第二个方法不会返回任何内容。相反,它只是执行授权检查,如果实体无权访问安全对象,则抛出 AccessDeniedException 异常

2.2. Older Versions of Spring Security

2.2.旧版本的 Spring Security

It’s worth noting that the AuthorizationManager interface was introduced in Spring Security 5.0. Prior to this interface, the primary method for authorization was via the AccessDecisionManager interface. While the AccessDecisionManager interface still exists in recent versions of Spring Security, it is deprecated and should be avoided in favor of AuthorizationManager.

值得注意的是,AuthorizationManager接口是在 Spring Security 5.0 中引入的。在此接口之前,授权的主要方法是通过 AccessDecisionManager 接口。虽然 AccessDecisionManager 接口仍存在于 Spring Security 的最新版本中,但它已被弃用,应避免使用 AuthorizationManager 而改用.

3. Implementations of AuthorizationManager

3.AuthorizationManager 的实现</em

Spring provides several implementations of the AuthorizationManager interface. In the following sections, we’ll take a look at several of them.

Spring 提供了多个 AuthorizationManager 接口的实现。在下面的章节中,我们将介绍其中的几种实现。

3.1. AuthenticatedAuthorizationManager

3.1.身份验证授权管理器</em

The first implementation we’ll look at is the AuthenticatedAuthorizationManager. Put simply, this class returns a positive authorization decision based solely on whether or not the entity is authenticated. Additionally, it supports three levels of authentication:

我们要了解的第一个实现是 AuthenticatedAuthorizationManager。简单地说,该类仅根据实体是否通过身份验证来返回肯定的授权决定。此外,该类还支持三种级别的身份验证:

  • anonymous: the entity is not authenticated
  • remember me: the entity is authenticated and is using remembered credentials
  • fully authenticated: the entity is authenticated and not using remembered credentials

Note that this is the default AuthorizationManager that Spring Boot creates for web-based applications. By default, all endpoints will allow access regardless of role or authority, as long as it comes from an authenticated entity.

请注意,这是 Spring Boot 为基于 Web 的应用程序创建的默认 AuthorizationManager 。默认情况下,只要访问来自经过验证的实体,所有端点都将允许访问,而不考虑角色或权限。

3.2. AuthoritiesAuthorizationManager

3.2.授权管理器</em

This implementation works similarly to the previous one, except it can make decisions based on multiple authorities. This is more suitable for complex applications where resources may need to be accessible by more than one authority.

这种实现方式与前一种类似,但它可以根据多个权限做出决定。这更适用于需要由多个权限访问资源的复杂应用程序。

Consider a blogging system that uses different roles to manage the publishing process. The resource for creating and saving an article might be accessible to both the Author and Editor roles. However, the resource for publishing is available to only the Editor role.

考虑一个使用不同角色来管理发布流程的博客系统。作者编辑角色都可以访问用于创建和保存文章的资源。但是,只有 Editor 角色可以访问用于发布的资源。

3.3. AuthorityAuthorizationManager

3.3.授权管理器</em

This implementation is fairly straightforward. It makes all of its authorization decisions based on whether the entity has a specific role.

这种实现方式相当简单明了。它根据实体是否具有特定角色来做出所有授权决定。

This implementation works well for simple applications where each resource requires a single role or authority. For example, it would work well for protecting a specific set of URLs to only entities with an Administrator role.

对于每个资源都需要单一角色或权限的简单应用,这种实现方式非常有效。例如,它可以很好地保护一组特定的 URL,使其只对具有 Administrator 角色的实体开放。

Note that this implementation delegates its decision-making to an instance of AuthoritiesAuthorizationManager. It’s also the implementation that Spring uses whenever we call hasRole() or hasAuthorities() while customizing a SecurityFilterChain.

请注意,该实现将决策委托给了 AuthoritiesAuthorizationManager 的实例。这也是 Spring 在自定义 SecurityFilterChain 时调用 hasRole()hasAuthorities() 时使用的实现。

3.4. RequestMatcherDelegatingAuthorizationManager

3.4.请求捕获器授权管理器</em

This implementation doesn’t actually make authorization decisions. Instead, it delegates to another implementation based on URL patterns, usually one of the above manager classes.

该实现实际上并不做出授权决定。相反,它会根据 URL 模式委托给另一个实现,通常是上述管理器类中的一个。

For example, if we have some URLs that are public and available to anyone, we could delegate those URLs to a no-op implementation that always returns a positive authorization. We could then delegate secured requests to an AuthoritiesAuthorizationManager that handles checking for roles.

例如,如果我们有一些 URL 是公开的,任何人都可以访问,那么我们可以将这些 URL 委托给总是返回肯定授权的无操作实现。然后,我们可以将安全请求委托给一个 AuthoritiesAuthorizationManager 来处理角色检查。

In fact, this is exactly what Spring does when we add a new request matcher to a SecurityFilterChain. Each time we configure a new request matcher and specify one or more required roles or authorities, Spring just creates a new instance of this class along with an appropriate delegate.

事实上,当我们向 SecurityFilterChain 中添加新请求匹配器时,这正是 Spring 所做的工作。每次我们配置新的请求匹配器并指定一个或多个所需的角色或授权时,Spring 都会创建该类的新实例以及相应的委托。

3.5. ObservationAuthorizationManager

3.5.观测授权管理器</em

The final implementation we’ll look at is the ObservationAuthorizationManager. This class is really just a wrapper around another implementation, with the added ability to log metrics related to authorization decisions. Spring will automatically use this implementation whenever a valid ObservationRegistry is available in the application.

我们要了解的最后一个实现是 ObservationAuthorizationManager。该类实际上只是另一种实现的封装,并增加了记录与授权决策相关的指标的功能。只要应用程序中存在有效的ObservationRegistry,Spring 就会自动使用该实现。

3.6. Other Implementations

3.6.其他执行方式

It’s worth mentioning that several other implementations exist in Spring Security. Most of them are related to the various Spring Security annotations used to secure methods:

值得一提的是,Spring Security 中还存在其他几种实现。其中大部分与用于确保方法安全的各种 Spring 安全注解有关:

  • SecuredAuthorizationManager -> @Secured
  • PreAuthorizeAuthorizationManager -> @PreAuthorize
  • PostAuthorizeAuthorizationManager -> @PostAuthorize

Essentially, any Spring Security annotation we can use to secure resources has a corresponding AuthorityManager implementation.

基本上,我们可以用来确保资源安全的任何 Spring 安全注解都有一个相应的 AuthorityManager 实现。

3.7. Using Multiple AuthorizationManagers

3.7.使用多个 AuthorizationManagers

In practice, we rarely ever use just a single instance of AuthorizationManager. Let’s take a look at an example SecurityFilterChain bean:

在实践中,我们很少只使用 AuthorizationManager 的一个实例。让我们来看一个 SecurityFilterChain Bean 的示例:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((authorize) -> authorize
        .requestMatchers("/posts/publish/**").hasRole("EDITOR")
        .requestMatchers("/posts/create/**").hasAnyRole("EDITOR", "AUTHOR")
        .anyRequest().permitAll());
    return http.build();
}

This example uses five different AuthorizationManager instances:

此示例使用了五个不同的 AuthorizationManager 实例:

  • The call to hasRole() creates an instance of AuthorityAuthorizationManager, which in turn delegates to a new instance of AuthoritiesAuthorizationManager.
  • The call to hasAnyRole() also creates an instance of AuthorityAuthorizationManager, which in turn delegates to a new instance of AuthoritiesAuthorizationManager.
  • The call to permitAll() uses a static no-op AuthorizationManager provided by Spring Security that always provides a positive authorization decision.

Additional request matchers with their own roles, along with any method-based annotations, would all create additional AuthorizationManager instances.

其他具有各自角色的请求匹配器以及任何基于方法的注释都将创建额外的 AuthorizationManager 实例。

4. Using a Custom AuthorizationManager

4.使用自定义 AuthorizationManager

The provided implementations above are sufficient for many applications. However, as with many interfaces in Spring, it is entirely possible to create a custom AuthorizationManager to suit whatever needs we have.

上述提供的实现足以满足许多应用程序的需求。然而,与 Spring 中的许多接口一样,我们完全可以创建自定义的 AuthorizationManager 来满足我们的任何需求。

Let’s define a custom AuthorizationManager:

让我们定义一个自定义的 AuthorizationManager

AuthorizationManager<RequestAuthorizationContext> customAuthManager() {
    return new AuthorizationManager<RequestAuthorizationContext>() {
        @Override
        public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
            // make authorization decision
        }
    };
}

We would then pass this instance while customizing the SecurityFilterChain:

然后,我们将在自定义 SecurityFilterChain 时传递此实例:

SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((authorize) ->
                    authorize.requestMatchers("/custom/**").access(customAuthManager())
    return http.build();
}

In this case, we’re making authorization decisions using a RequestAuthorizationContext. This class provides access to the underlying HTTP request, meaning we can make decisions based on things like cookies, headers, and more. We can also delegate to a third-party service, database, or cache, among other constructs, to make any type of authorization decision we want.

在本例中,我们使用 RequestAuthorizationContext 来做出授权决定。该类提供了对底层 HTTP 请求的访问权限,这意味着我们可以根据 cookie、标头等信息做出决策。我们还可以委托第三方服务、数据库或缓存等其他结构,以做出我们想要的任何类型的授权决定。

5. Conclusion

5.结论

In this article, we’ve taken a close look at how Spring Security handles authorization. We saw the generic AuthorizationManager interface and how its two methods make authorization decisions.

在本文中,我们仔细研究了 Spring Security 如何处理授权。我们看到了通用的 AuthorizationManager 接口及其两个方法是如何做出授权决定的。

We also saw various implementations of this implementation, and how they are used in various places in the Spring Security framework.

我们还看到了这种实现的各种实现,以及它们如何在 Spring 安全框架的不同地方使用。

Finally, we created a simple custom implementation that can be used to make any type of authorization decisions that we need in our applications.

最后,我们创建了一个简单的自定义实现,可用于在应用程序中做出我们需要的任何类型的授权决定。

As always, the code examples in this article are available over on GitHub.

与往常一样,本文中的代码示例可在 GitHub 上获取