在 Spring Security 6.1 中,AuthenticationManagers 是一个静态工厂工具类,用于快速创建和配置常用的 AuthenticationManager 实例。它简化了认证管理器的初始化过程,提供了多种预配置的工厂方法,适用于不同的认证场景。
下面是 AuthorizationManagers 的源码,如下:
package org.springframework.security.authorization;
import java.util.ArrayList;
import java.util.List;
/**
* 授权管理器的工厂类
* 提供创建组合式授权管理器的静态方法
* 支持 AND、OR、NOT 等逻辑组合多个授权决策
*/
public final class AuthorizationManagers {
/**
* 创建一个"任意通过"授权管理器
* 只要有一个授权管理器通过或弃权,最终决策即为通过
* 若所有管理器都拒绝,则返回拒绝决策
* 若没有提供任何管理器,默认返回拒绝决策
*
* @param <T> 被授权对象的类型
* @param managers 要组合的授权管理器列表
* @return 组合后的授权管理器
*/
@SafeVarargs
public static <T> AuthorizationManager<T> anyOf(AuthorizationManager<T>... managers) {
return anyOf(new AuthorizationDecision(false), managers);
}
/**
* 创建一个带默认决策的"任意通过"授权管理器
* 只要有一个授权管理器通过,最终决策即为通过
* 若所有管理器都弃权,返回指定的默认决策
*
* @param <T> 被授权对象的类型
* @param allAbstainDefaultDecision 所有管理器都弃权时的默认决策
* @param managers 要组合的授权管理器列表
* @return 组合后的授权管理器
* @since 6.3
*/
@SafeVarargs
public static <T> AuthorizationManager<T> anyOf(AuthorizationDecision allAbstainDefaultDecision,
AuthorizationManager<T>... managers) {
return (authentication, object) -> {
List<AuthorizationDecision> decisions = new ArrayList<>();
for (AuthorizationManager<T> manager : managers) {
// 逐个调用授权管理器进行决策
AuthorizationDecision decision = manager.check(authentication, object);
if (decision == null) { // 弃权决策,跳过
continue;
}
if (decision.isGranted()) { // 一旦有通过决策,立即返回
return decision;
}
decisions.add(decision); // 收集拒绝决策
}
if (decisions.isEmpty()) { // 所有管理器都弃权
return allAbstainDefaultDecision;
}
// 返回包含所有拒绝决策的组合决策
return new CompositeAuthorizationDecision(false, decisions);
};
}
/**
* 创建一个"全部通过"授权管理器
* 只有当所有授权管理器都通过或弃权时,最终决策才为通过
* 若有任何一个管理器拒绝,最终决策即为拒绝
* 若没有提供任何管理器,默认返回通过决策
*
* @param <T> 被授权对象的类型
* @param managers 要组合的授权管理器列表
* @return 组合后的授权管理器
*/
@SafeVarargs
public static <T> AuthorizationManager<T> allOf(AuthorizationManager<T>... managers) {
return allOf(new AuthorizationDecision(true), managers);
}
/**
* 创建一个带默认决策的"全部通过"授权管理器
* 只有当所有授权管理器都通过时,最终决策才为通过
* 若有任何一个管理器拒绝,立即返回拒绝决策
* 若所有管理器都弃权,返回指定的默认决策
*
* @param <T> 被授权对象的类型
* @param allAbstainDefaultDecision 所有管理器都弃权时的默认决策
* @param managers 要组合的授权管理器列表
* @return 组合后的授权管理器
* @since 6.3
*/
@SafeVarargs
public static <T> AuthorizationManager<T> allOf(AuthorizationDecision allAbstainDefaultDecision,
AuthorizationManager<T>... managers) {
return (authentication, object) -> {
List<AuthorizationDecision> decisions = new ArrayList<>();
for (AuthorizationManager<T> manager : managers) {
// 逐个调用授权管理器进行决策
AuthorizationDecision decision = manager.check(authentication, object);
if (decision == null) { // 弃权决策,跳过
continue;
}
if (!decision.isGranted()) { // 一旦有拒绝决策,立即返回
return decision;
}
decisions.add(decision); // 收集通过决策
}
if (decisions.isEmpty()) { // 所有管理器都弃权
return allAbstainDefaultDecision;
}
// 返回包含所有通过决策的组合决策
return new CompositeAuthorizationDecision(true, decisions);
};
}
/**
* 创建一个"取反"授权管理器
* 将给定授权管理器的决策结果取反
* 若原管理器返回通过,则取反后返回拒绝
* 若原管理器返回拒绝,则取反后返回通过
* 若原管理器弃权,则取反后也弃权
*
* @param <T> 被授权对象的类型
* @param manager 要取反的授权管理器
* @return 取反后的授权管理器
* @since 6.3
*/
public static <T> AuthorizationManager<T> not(AuthorizationManager<T> manager) {
return (authentication, object) -> {
// 调用原授权管理器获取决策
AuthorizationDecision decision = manager.check(authentication, object);
if (decision == null) { // 原管理器弃权
return null;
}
// 返回取反后的决策
return new NotAuthorizationDecision(decision);
};
}
//...
}上述源码中,主要提供了如下几个方法:
anyOf(AuthorizationManager<T>... managers) 创建一个“任意通过”授权管理器,只要有一个授权管理器通过或弃权,最终决策即为通过若所有管理器都拒绝,则返回拒绝决策若没有提供任何管理器,默认返回拒绝决策。
allOf(AuthorizationManager<T>... managers) 创建一个带默认决策的“全部通过”授权管理器只有当所有授权管理器都通过时,最终决策才为通过。若有任何一个管理器拒绝,立即返回拒绝决策。若所有管理器都弃权,返回指定的默认决策。
not(AuthorizationManager<T> manager) 创建一个“取反”授权管理器,将给定授权管理器的决策结果取反。若原管理器返回通过,则取反后返回拒绝。若原管理器返回拒绝,则取反后返回通过。若原管理器弃权,则取反后也弃权。
简单用法,如下:
http.authorizeHttpRequests(authorize -> authorize
// 需要具有 admin 角色权限才能访问 /sys 路径的请求
.requestMatchers("/sys/**").access(AuthorizationManagers.anyOf(
IpAddressAuthorizationManager.hasIpAddress("192.168.1.15"),
IpAddressAuthorizationManager.hasIpAddress("192.168.1.0/24")
))
.anyRequest().authenticated() // 其他请求需认证
)