欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > SpringSecurity中文文档(Servlet Authorization Architecture )

SpringSecurity中文文档(Servlet Authorization Architecture )

2024/10/24 7:27:57 来源:https://blog.csdn.net/znjy111/article/details/140264114  浏览:    关键词:SpringSecurity中文文档(Servlet Authorization Architecture )

Authorization

在确定了用户将如何进行身份验证之后,还需要配置应用程序的授权规则。

Spring Security 中的高级授权功能是其受欢迎的最有说服力的原因之一。无论您选择如何进行身份验证(无论是使用 Spring Security 提供的机制和提供者,还是与容器或其他非 Spring Security 身份验证授权机构集成) ,授权服务都可以在您的应用程序中以一致和简单的方式使用。

您应该考虑附加授权规则来请求 URI 和方法。在这两种情况下,您都可以侦听并响应每个授权检查发布的授权事件。下面还有大量关于 Spring Security 授权如何工作的细节,以及在建立了基本模型之后,如何对其进行微调。

Authorization Architecture

本节描述应用于授权的 SpringSecurity 体系结构。

Authorities

身份验证讨论所有身份验证实现如何存储 GrantedAuthority 对象列表。这些代表授予主体的权限。。GrantedAuthority 对象由 AuthenticationManager 插入到 Authentication 对象中,然后在进行授权决策时由 AccessDecisionManager 实例读取。

GrantedAuthority 接口只有一个方法:

String getAuthority();

AuthorizationManager 实例使用此方法来获取 GrantedAuthority 的精确 String 表示形式。通过返回一个 String 形式的表示,GrantedAuthority 可以被大多数 AuthorizationManager 实现轻松地“读取”。如果 GrantedAuthority 不能精确地表示为 String,那么 GrantedAuthority 被认为是“复杂的”,而 getAuthority ()必须返回 null。

一个复杂的 GrantedAuthority 的示例可能是一个实现,它存储了适用于不同客户账户号码的操作列表和权限阈值。将这种复杂的 GrantedAuthority 表示为一个字符串会相当困难。因此,getAuthority() 方法应该返回 null。这表示任何 AuthorizationManager 需要支持特定的 GrantedAuthority 实现以理解其内容。

Spring Security 包括一个具体的 GrantedAuthority 实现:SimpleGrantedAuthority。这个实现允许任何用户指定的字符串被转换为 GrantedAuthority。安全架构中包含的所有 AuthenticationProvider 实例都使用 SimpleGrantedAuthority 来填充 Authentication 对象。

默认情况下,基于角色的授权规则包括 ROLE_ 作为前缀。这意味着如果有需要安全上下文具有“USER”角色的授权规则,Spring Security 默认会查找返回“ROLE_USER”的 GrantedAuthority#getAuthority。

可以使用 GrantedAuthorityDefauls.GrantedAuthorityDefault 存在来自定义前缀,以便用于基于角色的授权规则。

您可以通过公开 GrantedAuthorityDefault bean 来配置授权规则以使用不同的前缀,如下所示:

Custom MethodSecurityExpressionHandler

@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {return new GrantedAuthorityDefaults("MYPREFIX_");
}

使用静态方法公开 GrantedAuthorityDefault,以确保 Spring 在初始化 Spring Security 的方法 Security@Configuration 类之前发布它

Invocation Handling

SpringSecurity 提供了拦截器来控制对安全对象(如方法调用或 Web 请求)的访问。AuthorizationManager 实例对是否允许继续进行调用作出预调用决策。此外,AuthorizationManager 实例在调用后决定是否可以返回给定的值。

The AuthorizationManager

AuthorizationManager 取代 AccessDecisionManager 和 AccessDecisionVoter。

鼓励自定义 AccessDecisionManager 或 AccessDecisionVoter 的应用程序更改为使用 AuthorizationManager。

AuthorizationManager 由 Spring Security 的基于请求、基于方法和基于消息的授权组件调用,并负责制定最终的访问控制决策。AuthorizationManager 接口包含两个方法:

AuthorizationDecision check(Supplier<Authentication> authentication, Object secureObject);default AuthorizationDecision verify(Supplier<Authentication> authentication, Object secureObject)throws AccessDeniedException {// ...
}

AuthorizationManager 的 check 方法被传递所有它需要的信息,以便做出授权决策。特别是,传递安全 Object 允许检查实际安全对象调用中的所有参数。例如,假设安全对象是一个 MethodInvocation。很容易查询 MethodInvocation 是否有任何 Customer 参数,然后实现一些安全逻辑在 AuthorizationManager 中,以确保主体被允许对该客户进行操作。实现被期望返回一个正值的 AuthorizationDecision,如果访问被授权;负值的 AuthorizationDecision,如果访问被拒绝;以及一个 null AuthorizationDecision,当不作出决定时。

verify 方法调用 check 方法,并在遇到负值的 AuthorizationDecision 时,随后抛出一个 AccessDeniedException。

Delegate-based AuthorizationManager Implementations

虽然用户可以实现自己的 AuthorizationManager 来控制授权的所有方面,但 Spring Security 提供了一个授权 AuthorizationManager,它可以与各个 AuthorizationManager 协作。

RequestMatchergeneratingAuthorizationManager 将使请求与最合适的委托 AuthorizationManager 匹配。

Authorization Manager Implementations 说明了相关的类。

authorizationhierarchy

*Figure 1. Authorization Manager Implementations*

使用这种方法,可以对授权决策轮询 AuthorizationManager 实现的组合。

AuthorityAuthorizationManager

Spring Security提供的最常见的 AuthorizationManager 是 AuthorityAuthorizationManager。它配置了一组给定的权限来查找当前的Authentication。如果身份验证包含任何配置的权限,它将返回正的 AuthorizationDecision。否则它将返回一个否定的授权决策。

AuthenticatedAuthorizationManager

另一个管理器是 AuthenticatedAuthorizationManager。它可以用来区分匿名、完全认证和记住我认证的用户。许多网站允许在记住我认证下进行某些有限的访问,但要求用户通过登录来确认他们的身份,以便获得完全访问权限。

AuthorizationManagers

AuthorizationManager 中还有一些有用的静态工厂,可以将各个 AuthorizationManager 组合成更复杂的表达式。

Custom Authorization Managers

显然,您也可以实现一个自定义的 AuthorizationManager,并且可以在其中放入您想要的几乎任何访问控制逻辑。它可能与您的应用程序(业务逻辑相关)有关,也可能实现一些安全管理逻辑。例如,您可以创建一个实现,它可以查询 Open Policy Agent 或您自己的授权数据库。

您将在 Spring 网站上找到一篇 blog article ,其中描述了如何使用遗留的 AccessDecisionVoter 来拒绝实时访问那些帐户已被暂停的用户。您可以通过实现 AuthorizationManager 来实现相同的结果。

Adapting AccessDecisionManager and AccessDecisionVoters

在 AuthorizationManager 之前,Spring Security 发布了 AccessDecisionManager 和 AccessDecisionVoter。

在某些情况下,比如迁移较旧的应用程序,可能需要引入一个 AuthorizationManager 来调用 AccessDecisionManager 或 AccessDecisionVoter。

要调用现有的 AccessDecisionManager,可以执行以下操作:

Adapting an AccessDecisionManager

@Component
public class AccessDecisionManagerAuthorizationManagerAdapter implements AuthorizationManager {private final AccessDecisionManager accessDecisionManager;private final SecurityMetadataSource securityMetadataSource;@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {try {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);this.accessDecisionManager.decide(authentication.get(), object, attributes);return new AuthorizationDecision(true);} catch (AccessDeniedException ex) {return new AuthorizationDecision(false);}}@Overridepublic void verify(Supplier<Authentication> authentication, Object object) {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);this.accessDecisionManager.decide(authentication.get(), object, attributes);}
}

然后连接到你的安全过滤器链。

或者只调用 AccessDecisionVoter,你可以这样做:

Adapting an AccessDecisionVoter

@Component
public class AccessDecisionVoterAuthorizationManagerAdapter implements AuthorizationManager {private final AccessDecisionVoter accessDecisionVoter;private final SecurityMetadataSource securityMetadataSource;@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);int decision = this.accessDecisionVoter.vote(authentication.get(), object, attributes);switch (decision) {case ACCESS_GRANTED:return new AuthorizationDecision(true);case ACCESS_DENIED:return new AuthorizationDecision(false);}return null;}
}

然后连接到你的安全过滤器链。

Hierarchical Roles

应用程序中的特定角色应该自动“包含”其他角色,这是一个常见的要求。例如,在具有“管理员”和“用户”角色概念的应用程序中,您可能希望管理员能够做普通用户能够做的所有事情。要实现这一点,您可以确保所有管理用户也被分配了“用户”角色。或者,您可以修改每个需要“user”角色的访问约束,使其也包含“admin”角色。如果您的应用程序中有许多不同的角色,这可能会变得相当复杂。

角色层次结构的使用允许您配置哪些角色(或权限)应该包括其他角色。

这支持基于过滤器的授权在 HttpSecurity#authorizeHttpRequests 中,以及通过 DefaultMethodSecurityExpressionHandler 进行基于方法的安全授权,SecuredAuthorizationManager 用于 @Secured,Jsr250AuthorizationManager 用于 JSR-250 注解。您可以以以下方式一次性配置它们的行为:

@Bean
static RoleHierarchy roleHierarchy() {return RoleHierarchyImpl.withDefaultRolePrefix().role("ADMIN").implies("STAFF").role("STAFF").implies("USER").role("USER").implies("GUEST").build();
}// and, if using pre-post method security also add
@Bean
static MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();expressionHandler.setRoleHierarchy(roleHierarchy);return expressionHandler;
}

在这里,我们有四个角色的层次结构 ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST。一个具有 ROLE_ADMIN 认证的用户,在评估任何基于过滤器或方法的安全约束时,将表现得好像他们拥有所有四个角色。

角色层次结构为您的应用程序提供了简化访问控制配置数据的便捷方式,以及减少您需要分配给用户的角色权限的数量。对于更复杂的需求,您可能希望定义一个逻辑映射,将您的应用程序所需的具体访问权限与分配给用户的角色之间进行转换,并在加载用户信息时进行转换。

Legacy Authorization Components

SpringSecurity 包含一些遗留组件。因为它们还没有被删除,所以出于历史目的包含了文档。他们推荐的替代品在上面。

The AccessDecisionManager

AccessDecisionManager 由 AbstractSecurityInterceptor 调用,负责做出最终的访问控制决策。AccessDecisionManager 接口包含三个方法:

void decide(Authentication authentication, Object secureObject,Collection<ConfigAttribute> attrs) throws AccessDeniedException;boolean supports(ConfigAttribute attribute);boolean supports(Class clazz);

AccessDecisionManager 的 decide 方法被传递所有它需要的信息,以便做出授权决策。特别是,传递安全 Object 允许检查实际安全对象调用中的所有参数。例如,假设安全对象是一个 MethodInvocation。您可以查询 MethodInvocation 是否有任何 Customer 参数,然后实现一些安全逻辑在 AccessDecisionManager 中,以确保主体被允许对该客户进行操作。实现被期望如果访问被拒绝则抛出一个 AccessDeniedException。

supports(ConfigAttribute) 方法在启动时被 AbstractSecurityInterceptor 调用,以确定 AccessDecisionManager 是否可以处理传递的 ConfigAttribute。supports(Class) 方法被安全拦截器实现调用,以确保配置的 AccessDecisionManager 支持安全拦截器呈现的安全 Object 的类型。

Voting-Based AccessDecisionManager Implementations

虽然用户可以实现自己的 AccessDecisionManager 来控制授权的所有方面,但 Spring Security 包括几个基于投票的 AccessDecisionManager 实现。投票决策管理器描述了相关的类。

下图显示了 AccessDecisionManager 接口:

access decision voting

*Figure 2. Voting Decision Manager*

通过使用这种方法,对授权决策进行一系列 AccessDecisionVoter 实现轮询。然后,AccessDecisionManager 根据对投票的评估决定是否抛出 AccessDeniedException。

AccessDecisionVoter 接口有三个方法:

int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);boolean supports(ConfigAttribute attribute);boolean supports(Class clazz);

具体实现返回一个整数,可能的值反映在 AccessDecisionVoter 静态字段中,这些字段被命名为 ACCESS_ABSTAIN、ACCESS_DENIED 和 ACCESS_GRANTED。一个投票实现如果对授权决策没有意见,则返回 ACCESS_ABSTAIN。如果它确实有意见,它必须返回 ACCESS_DENIED 或 ACCESS_GRANTED。

Spring Security 提供了三个具体的 AccessDecisionManager 实现,以计算投票。ConsensusBased 实现基于非弃权投票的共识来授予或拒绝访问。提供了属性来控制在投票平局或所有投票都弃权的情况下的行为。AffirmativeBased 实现如果收到一个或多个 ACCESS_GRANTED 投票(换句话说,只要有一个授权投票,就忽略否认投票),则授予访问权限。与 ConsensusBased 实现类似,有一个参数来控制如果所有投票者都弃权的行为。UnanimousBased 实现期望获得一致的 ACCESS_GRANTED 投票,以便授予访问权限,忽略弃权。如果有任何 ACCESS_DENIED 投票,则拒绝访问。与其他实现一样,如果所有投票者都弃权,也有一个参数来控制行为。

您可以实现一个自定义 AccessDecisionManager,它以不同的方式计算选票。例如,来自特定 AccessDecisionVoter 的投票可能获得额外的权重,而来自特定选民的否决投票可能具有否决权效果。

RoleVoter

Spring Security 提供的最常用的 AccessDecisionVoter 是 RoleVoter,它将配置属性视为角色名,如果用户已经分配了该角色,它将投票授予访问权。

如果任何 ConfigAttribute 以 ROLE _ 前缀开头,它将进行表决。如果有一个 GrantedAuthority 返回的 String 表示(来自 getAuthority ()方法)与一个或多个以 ROLE _ 前缀开头的 ConfigAttritribute 完全相等,它将投票授予访问权。如果没有与以 ROLE _ 开头的任何 ConfigAttribute 完全匹配,RoleVoter 将投票拒绝访问。如果没有以 ROLE _ 开头的 ConfigAttribute,则选民弃权。

AuthenticatedVoter

我们隐式看到的另一个选民是 AuthenticatedVoter,它可以用来区分匿名、完全身份验证和 remember-me 身份验证用户。许多站点允许在 remember-me 身份验证下进行某些有限的访问,但是需要用户通过登录进行完全访问来确认他们的身份。

当我们使用 IS _ AUTHENTICATION _ ANONYMOUSLY 属性授予匿名访问权限时,AuthenticatedVoter 正在处理该属性。有关更多信息,请参见 AuthenticatedVoter。

Custom Voters

您还可以实现一个自定义 AccessDecisionVoter,并在其中放入几乎任何您想要的访问控制逻辑。它可能特定于您的应用程序(与业务逻辑相关) ,也可能实现某些安全管理逻辑。例如,在 Spring 网站上,您可以找到一篇博客文章,其中描述了如何使用投票者拒绝实时访问其帐户已被暂停的用户。

after invocation

*Figure 3. After Invocation Implementation*

像 Spring Security 的许多其他部分一样,AfterInvocationManager 有一个具体的实现 AfterInvocationProviderManager,它轮询 AfterInvocationProvider 列表。允许每个 AfterInvocationProvider 修改返回对象或抛出 AccessDeniedException。实际上,多个提供程序可以修改对象,因为前一个提供程序的结果将传递给列表中的下一个提供程序。

请注意,如果您使用 AfterInvocationManager,您仍然需要配置属性,以允许 MethodSecurityInterceptor 的 AccessDecisionManager 允许一个操作。如果您使用 Spring Security 通常包含的 AccessDecisionManager 实现,对于特定安全方法调用的未定义配置属性将导致每个 AccessDecisionVoter 弃权。相应地,如果 AccessDecisionManager 属性“allowIfAllAbstainDecisions”为 false,将抛出一个 AccessDeniedException。您可以通过以下两种方式之一避免这个潜在的问题:(i)将“allowIfAllAbstainDecisions”设置为 true(尽管这通常不推荐),或者(ii)简单地确保至少有一个配置属性,AccessDecisionVoter 将投票授予访问权限。后一种(推荐)方法通常通过配置一个 ROLE_USER 或 ROLE_AUTHENTICATED 属性来实现。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com