@Configuration
@EnableMethodSecurity
@Slf4j
public class SecurityConfig {
}
// 导入配置类MethodSecuritySelector
@Import(MethodSecuritySelector.class)
public @interface EnableMethodSecurity {
}
// 导入注解相关的配置类,由配置类导入对应处理注解的拦截器
public class MethodSecuritySelector implements ImportSelector {
// 自动代理的注册器
// 导入创建代理对象的Bean以及每一个注解对应的拦截器的切面对象的Bean
private final AutoProxyRegistrarSelector autoProxy = new AutoProxyRegistrarSelector();
@Override
public String[] selectImports(@NonNull AnnotationMetadata importMetadata) {
// 如果导入类不存在EnableMethodSecurity注解,不处理
if (!importMetadata.hasAnnotation(EnableMethodSecurity.class.getName())) {
return new String[0];
}
// 获取该注解的信息
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
// 导入创建代理对象的Bean以及每一个注解对应的拦截器的切面对象的Bean
List<String> imports = new ArrayList<>(Arrays.asList(this.autoProxy.selectImports(importMetadata)));
// 判断该注解开启的认证授权注解有哪些
// 如果开启了pre/post,表示开启了Pre|PostAuthorize,Pre|PostFilter
if (annotation.prePostEnabled()) {
imports.add(PrePostMethodSecurityConfiguration.class.getName());
}
// 如果开启了secured,表示启用Secured注解
if (annotation.securedEnabled()) {
imports.add(SecuredMethodSecurityConfiguration.class.getName());
}
// 如果开启了jsr250,表示启用RolesAllowed.class, DenyAll.class, PermitAll.class注解
if (annotation.jsr250Enabled()) {
imports.add(Jsr250MethodSecurityConfiguration.class.getName());
}
// 根据开启的调来导入对应处理的MethodInterceptor拦截器的Bean
return imports.toArray(new String[0]);
}
// 自动代理的注册器
// 导入创建代理对象的Bean以及每一个注解对应的拦截器的切面对象的Bean
private static final class AutoProxyRegistrarSelector extends AdviceModeImportSelector<EnableMethodSecurity> {
// 导入创建代理对象的Bean以及每一个注解对应的拦截器的切面对象的Bean
private static final String[] IMPORTS = new String[]{AutoProxyRegistrar.class.getName(), MethodSecurityAdvisorRegistrar.class.getName()};
private static final String[] ASPECTJ_IMPORTS = new String[]{MethodSecurityAspectJAutoProxyRegistrar.class.getName()};
@Override
public String[] selectImports(@NonNull AdviceMode adviceMode) {
// 代理模式,导入IMPORTS中的两个Bean
if (adviceMode == AdviceMode.PROXY) {
return IMPORTS;
}
// ASPECTJ模式,导入ASPECTJ_IMPORTS的两个Bean
if (adviceMode == AdviceMode.ASPECTJ) {
return ASPECTJ_IMPORTS;
}
throw new IllegalStateException("AdviceMode '" + adviceMode + "' is not supported");
}
}
}
// 负责注入创建AOP对象的BeanPostProcessor
// 事务注解也会注入的这类,它会负责注入创建代理对象的BeanPostProcessor
// 用来给目标类创建代理对象
public class AutoProxyRegistrar {
// 注册Bean
// importingClassMetadata是正在解析的配置类对应的元数据信息,也就是标注@EnableTransactionManagement这个类的配置类
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取配置类上的所有注解
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
// 遍历所有的注解
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
// 找到一些符合AOP条件的共性,mode,proxyTargetClass等等
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
// 如果符合这个条件,表示当前类需要进行AOP
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
// 判断当前配置类的代理模式
if (mode == AdviceMode.PROXY) {
// 注册创建AOP代理对象的BeanPostProcessor,InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
// 如果proxyTargetClass为true,表示使用CGLIB代理
/*
三种情况
1. proxyTargetClass =false(默认值) 目标实现了接口 JDK代理
2. proxyTargetClass =false(默认值) 目标未实现接口 CGLIB代理
3. proxyTargetClass =true 总是CGLIB代理
*/
if ((Boolean) proxyTargetClass) {
// 强制设置创建代理的使用使用CGLIB代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
// 导入每一个注解对应的拦截器的切面对象的Bean
public class MethodSecurityAdvisorRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册认证授权注解对应的切面或者拦截器
// 命名规则: 注解类名首字符小写 + Authorization +[ Advisor | MethodInterceptor ]
// 例如: preFilterAuthorization要注册的切面或者拦截器为: PreFilterAuthorizationMethodInterceptor,用于处理PreFilter注解
registerAsAdvisor("preFilterAuthorization", registry);
registerAsAdvisor("preAuthorizeAuthorization", registry);
registerAsAdvisor("postFilterAuthorization", registry);
registerAsAdvisor("postAuthorizeAuthorization", registry);
registerAsAdvisor("securedAuthorization", registry);
registerAsAdvisor("jsr250Authorization", registry);
}
/**
* 注册认证授权注解对应的切面
* 命名规则: 注解类名首字符小写 + Authorization +[ Advisor | MethodInterceptor ]
* 例如: preFilterAuthorization要注册的切面或者拦截器为: PreFilterAuthorizationMethodInterceptor,用于处理PreFilter注解
*
* @param prefix 认证授权注解对应的切面对应的前缀,这些注解切面或者切面拦截器按照一定的规则命名的
* @param registry Bean的注册表
*/
private void registerAsAdvisor(String prefix, BeanDefinitionRegistry registry) {
// 先查看是否有指定注解前缀(指定注解名称)类型的切面,如果存在增强该注解的切面,不处理
String advisorName = prefix + "Advisor";
if (registry.containsBeanDefinition(advisorName)) {
return;
}
// 先查看是否有指定注解前缀(指定注解名称)类型的切面拦截器,如果存在增强该注解的切面拦截器,不处理
String interceptorName = prefix + "MethodInterceptor";
if (!registry.containsBeanDefinition(interceptorName)) {
return;
}
// 该注解前缀不存在对应的切面以及拦截器,那么就是用默认的命名规则获得对应的Bean: beanName: 注解前缀(preFilterAuthorization) + 拦截器后缀(MethodInterceptor)
BeanDefinition definition = registry.getBeanDefinition(interceptorName);
// 如果不是RootBeanDefinition类型的Bean定义,不处理
if (!(definition instanceof RootBeanDefinition)) {
return;
}
// 通过拦截器构造上一个切面注册到Spring容器中
RootBeanDefinition advisor = new RootBeanDefinition((RootBeanDefinition) definition);
advisor.setTargetType(Advisor.class);
registry.registerBeanDefinition(prefix + "Advisor", advisor);
}
}
public class PrePostMethodSecurityConfiguration {
// 注册@PreFilter的拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor preFilterAuthorizationMethodInterceptor(
// 设置角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
// 注解表达式的处理器
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
// 创建处理@PreFilter的拦截器
PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
strategyProvider.ifAvailable(preFilter::setSecurityContextHolderStrategy);
// 设置表达式处理器
preFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
return preFilter;
}
// 注册@PreAuthorize的拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
// 设置角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
// 注解表达式的处理器
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
// 授权事件的分发器
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
// 观察者注册表,监控授权过程中的操作
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
// 创建处理PreAuthorize注解的授权管理器
PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
// 设置表达式处理器
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
// 创建PreAuthorize注解的拦截器,其中有@PreAuthorize,@Secured,@DenyAll,@PermitAll,@RolesAllowed效果都是一样,在授权预授权
AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor.preAuthorize(manager(manager, registryProvider));
strategyProvider.ifAvailable(preAuthorize::setSecurityContextHolderStrategy);
eventPublisherProvider.ifAvailable(preAuthorize::setAuthorizationEventPublisher);
return preAuthorize;
}
// 注册@PostAuthorize的拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
// 设置角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
// 注解表达式的处理器
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
// 授权事件的分发器
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
// 观察者注册表,监控授权过程中的操作
ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
// 创建处理PostAuthorize注解的授权管理器
PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
// 设置表达式处理器
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
// 创建PostAuthorize注解的拦截器
AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor.postAuthorize(manager(manager, registryProvider));
strategyProvider.ifAvailable(postAuthorize::setSecurityContextHolderStrategy);
eventPublisherProvider.ifAvailable(postAuthorize::setAuthorizationEventPublisher);
return postAuthorize;
}
// 注册PostFilter的拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor postFilterAuthorizationMethodInterceptor(
// 设置角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
// 注解表达式的处理器
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider, ApplicationContext context) {
// 创建处理@PostFilter的拦截器
PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
strategyProvider.ifAvailable(postFilter::setSecurityContextHolderStrategy);
// 设置表达式处理器
postFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
return postFilter;
}
// 创建一个延迟观察授权管理器
public static <T> AuthorizationManager<T> manager(AuthorizationManager<T> delegate, ObjectProvider<ObservationRegistry> registryProvider) {
return new DeferringObservationAuthorizationManager<>(registryProvider, delegate);
}
}
// 延迟的方法注解表达式处理器
public class DeferringMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
// 方法注解表达式处理器
private final DefaultMethodSecurityExpressionHandler expressionHandler;
private DeferringMethodSecurityExpressionHandler(
// 方法注解表达式处理器
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
// 角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext applicationContext) {
// 如果不存在给定的表达式处理器,那就返回默认的表达式处理器
this.expressionHandler = expressionHandlerProvider.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, applicationContext));
}
// 默认的表达式处理器
public static MethodSecurityExpressionHandler defaultExpressionHandler(ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext context) {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
// 设置指定的角色名前缀
defaultsProvider.ifAvailable((d) -> handler.setDefaultRolePrefix(d.getRolePrefix()));
// 设置上下文
handler.setApplicationContext(context);
return handler;
}
// 获取表达式解析器,返回的就是SpelExpressionParser
@Override
public ExpressionParser getExpressionParser() {
return this.expressionHandler.getExpressionParser();
}
// 创建计算的上下文对象
@Override
public EvaluationContext createEvaluationContext(Authentication authentication, MethodInvocation invocation) {
return this.expressionHandler.createEvaluationContext(authentication, invocation);
}
// 创建计算的上下文对象
@Override
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation invocation) {
return this.expressionHandler.createEvaluationContext(authentication, invocation);
}
// 对目标对象进行过滤操作
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
return this.expressionHandler.filter(filterTarget, filterExpression, ctx);
}
// 设置返回结果到计算上下文中
@Override
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
this.expressionHandler.setReturnObject(returnObject, ctx);
}
}
/**
* 实际上该类为{@link DefaultMethodSecurityExpressionHandler}
*/
public class MethodSecurityExpressionHandler {
}
public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpressionHandler<MethodInvocation> implements MethodSecurityExpressionHandler {
// 默认的角色前缀
private String defaultRolePrefix = "ROLE_";
public DefaultMethodSecurityExpressionHandler() {
}
// 创建内置的标准计算上下文对象
@Override
public StandardEvaluationContext createEvaluationContextInternal(Authentication auth, MethodInvocation mi) {
return new MethodSecurityEvaluationContext(auth, mi, getParameterNameDiscoverer());
}
// 创建注解表达式的计算上下文
@Override
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation mi) {
// 创建注解的表达式根对象
MethodSecurityExpressionOperations root = createSecurityExpressionRoot(authentication, mi);
// 创建注解表达式的计算上下文
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(root, mi, getParameterNameDiscoverer());
// 设置Bean的解析器
ctx.setBeanResolver(getBeanResolver());
return ctx;
}
// 创建注解的表达式根对象
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
return createSecurityExpressionRoot(() -> authentication, invocation);
}
// 创建注解的表达式根对象
private MethodSecurityExpressionOperations createSecurityExpressionRoot(Supplier<Authentication> authentication, MethodInvocation invocation) {
// 保存认证信息
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
// 设置当前方法所在的目标对象
root.setThis(invocation.getThis());
//设置权限表达式计算器
root.setPermissionEvaluator(getPermissionEvaluator());
// 设置解析器
root.setTrustResolver(getTrustResolver());
// 设置角色的层级关系
root.setRoleHierarchy(getRoleHierarchy());
// 设置默认的角色前缀
root.setDefaultRolePrefix(getDefaultRolePrefix());
return root;
}
// 执行过滤操作
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
// 获取上下文的根对象
MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject().getValue();
// 过滤集合
if (filterTarget instanceof Collection) {
return filterCollection((Collection<?>) filterTarget, filterExpression, ctx, rootObject);
}
// 过滤数组
if (filterTarget.getClass().isArray()) {
return filterArray((Object[]) filterTarget, filterExpression, ctx, rootObject);
}
// 过滤Map
if (filterTarget instanceof Map) {
return filterMap((Map<?, ?>) filterTarget, filterExpression, ctx, rootObject);
}
// 过滤流
if (filterTarget instanceof Stream) {
return filterStream((Stream<?>) filterTarget, filterExpression, ctx, rootObject);
}
// 其他类型不支持过滤
throw new IllegalArgumentException("Filter target must be a collection, array, map or stream type, but was " + filterTarget);
}
// 过滤集合,Set/List/Collection
private <T> Object filterCollection(Collection<T> filterTarget, Expression filterExpression, EvaluationContext ctx, MethodSecurityExpressionOperations rootObject) {
// 需要保留的集合
List<T> retain = new ArrayList<>(filterTarget.size());
// 遍历需要过滤的对象
for (T filterObject : filterTarget) {
// 设置正在过滤的目标对象
rootObject.setFilterObject(filterObject);
// 如果注解的表达式为true,则保留当前这笔数据
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retain.add(filterObject);
}
}
// 删除过滤之前的所有数据
filterTarget.clear();
// 再保存过滤之后的数据
filterTarget.addAll(retain);
// 返回目标对象
return filterTarget;
}
// 过滤数组
public Object filterArray(Object[] filterTarget, Expression filterExpression, EvaluationContext ctx, MethodSecurityExpressionOperations rootObject) {
// 需要保留的数组
List<Object> retain = new ArrayList<>(filterTarget.length);
// 遍历需要过滤的对象
for (Object filterObject : filterTarget) {
// 设置正在过滤的目标对象
rootObject.setFilterObject(filterObject);
// 如果注解的表达式为true,则保留当前这笔数据
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
// 保留当前这笔数据
retain.add(filterObject);
}
}
// 创建一个新数组
Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(), retain.size());
// 将保留符合条件的数据装入数组中
for (int i = 0; i < retain.size(); i++) {
filtered[i] = retain.get(i);
}
// 返回过滤后的数组
return filtered;
}
// 过滤map
public <K, V> Object filterMap(final Map<K, V> filterTarget, Expression filterExpression, EvaluationContext ctx, MethodSecurityExpressionOperations rootObject) {
// 最终需要保留的Map
Map<K, V> retain = new LinkedHashMap<>(filterTarget.size());
// 遍历要过滤的对象
for (Map.Entry<K, V> filterObject : filterTarget.entrySet()) {
// 设置正在过滤的对象
rootObject.setFilterObject(filterObject);
// 如果注解的表达式为true,则保留当前这笔数据
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retain.put(filterObject.getKey(), filterObject.getValue());
}
}
// 删除过滤之前的所有数据
filterTarget.clear();
// 再保存过滤之后的数据
filterTarget.putAll(retain);
// 返回目标对象
return filterTarget;
}
// 过滤Stream参数
public Object filterStream(final Stream<?> filterTarget, Expression filterExpression, EvaluationContext ctx, MethodSecurityExpressionOperations rootObject) {
// 根据表达式进行过滤
return filterTarget.filter((filterObject) -> {
// 设置过滤的对象
rootObject.setFilterObject(filterObject);
// 根据表达式进行过滤,只过滤符合条件的数据
return ExpressionUtils.evaluateAsBoolean(filterExpression, ctx);
}).onClose(filterTarget::close);
}
// 设置最终的返回值
@Override
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
((MethodSecurityExpressionOperations) ctx.getRootObject().getValue()).setReturnObject(returnObject);
}
// 设置默认的角色前缀,默认为ROLE_
public void setDefaultRolePrefix(String defaultRolePrefix) {
this.defaultRolePrefix = defaultRolePrefix;
}
// 获取默认的角色前缀
protected String getDefaultRolePrefix() {
return this.defaultRolePrefix;
}
}
// 处理@Secured注解拦截器的配置类
public class SecuredMethodSecurityConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor securedAuthorizationMethodInterceptor(
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
// 观察者注册表,监控授权过程中的操作
ObjectProvider<ObservationRegistry> registryProvider) {
// 处理@Secure注解的授权管理器
SecuredAuthorizationManager secured = new SecuredAuthorizationManager();
SecurityContextHolderStrategy strategy = strategyProvider.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
// 创建延迟的授权管理器
AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(registryProvider, secured);
// 创建@Secured注解的拦截器,其中有@PreAuthorize,@Secured,@DenyAll,@PermitAll,@RolesAllowed效果都是一样,在授权预授权
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor.secured(manager);
interceptor.setSecurityContextHolderStrategy(strategy);
return interceptor;
}
}
// 处理Jsr250注解拦截器的配置类
public class Jsr250MethodSecurityConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor jsr250AuthorizationMethodInterceptor(
// 设置角色名称前缀的Bean
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
// 获取SecurityContextHolder的策略对应的Bean
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
// 观察者注册表,监控授权过程中的操作
ObjectProvider<ObservationRegistry> registryProvider) {
// 处理Jsr250注解的授权管理器
Jsr250AuthorizationManager jsr250 = new Jsr250AuthorizationManager();
// 设置角色前缀
defaultsProvider.ifAvailable((d) -> jsr250.setRolePrefix(d.getRolePrefix()));
SecurityContextHolderStrategy strategy = strategyProvider.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
// 创建延迟的授权管理器
AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(registryProvider, jsr250);
// 创建jsr250注解的拦截器,其中有@PreAuthorize,@Secured,@DenyAll,@PermitAll,@RolesAllowed效果都是一样,在授权预授权
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor.jsr250(manager);
interceptor.setSecurityContextHolderStrategy(strategy);
return interceptor;
}
}
// 方法拦截之前的授权管理器(其中有@PreAuthorize,@Secured,@DenyAll,@PermitAll,@RolesAllowed)
public class AuthorizationManagerBeforeMethodInterceptor implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
// SecurityContextHolderStrategy持久化策略
private Supplier<SecurityContextHolderStrategy> securityContextHolderStrategy = SecurityContextHolder::getContextHolderStrategy;
// 当前拦截器的切点,就是该注解对应的表达式匹配器
private final Pointcut pointcut;
// 授权管理器
private final AuthorizationManager<MethodInvocation> authorizationManager;
// 第一个的顺序
private int order = AuthorizationInterceptorsOrder.FIRST.getOrder();
// 授权的事件分发器,默认不发布任何事件,可以自己设置
private AuthorizationEventPublisher eventPublisher = AuthorizationManagerBeforeMethodInterceptor::noPublish;
public AuthorizationManagerBeforeMethodInterceptor(Pointcut pointcut, AuthorizationManager<MethodInvocation> authorizationManager) {
this.pointcut = pointcut;
this.authorizationManager = authorizationManager;
}
// 创建处理@PreAuthorize注解的拦截器
public static AuthorizationManagerBeforeMethodInterceptor preAuthorize() {
return preAuthorize(new PreAuthorizeAuthorizationManager());
}
// 指定处理@PreAuthorize的授权管理器,并创建AuthorizationManagerBeforeMethodInterceptor对象
public static AuthorizationManagerBeforeMethodInterceptor preAuthorize(AuthorizationManager<MethodInvocation> authorizationManager) {
AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(PreAuthorize.class), authorizationManager);
interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());
return interceptor;
}
// 创建处理@Secured注解的拦截器
public static AuthorizationManagerBeforeMethodInterceptor secured() {
return secured(new SecuredAuthorizationManager());
}
// 指定处理@Secured的授权管理器,并创建AuthorizationManagerBeforeMethodInterceptor对象
public static AuthorizationManagerBeforeMethodInterceptor secured(AuthorizationManager<MethodInvocation> authorizationManager) {
AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(Secured.class), authorizationManager);
interceptor.setOrder(AuthorizationInterceptorsOrder.SECURED.getOrder());
return interceptor;
}
// 创建处理Jsr250注解的拦截器
public static AuthorizationManagerBeforeMethodInterceptor jsr250() {
return jsr250(new Jsr250AuthorizationManager());
}
// 创建处理Jsr250注解的拦截器
// 指定处理Jsr250注解的授权管理器,并创建AuthorizationManagerBeforeMethodInterceptor对象
public static AuthorizationManagerBeforeMethodInterceptor jsr250(AuthorizationManager<MethodInvocation> authorizationManager) {
AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(RolesAllowed.class, DenyAll.class, PermitAll.class), authorizationManager);
interceptor.setOrder(AuthorizationInterceptorsOrder.JSR250.getOrder());
return interceptor;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 尝试授权操作
this.attemptAuthorization(mi);
// 放行到下一个拦截器
return mi.proceed();
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
// 获取通知,就是当前Before拦截器对象
@Override
public Advice getAdvice() {
return this;
}
// 尝试授权操作
private void attemptAuthorization(MethodInvocation mi) {
// 获取到认证信息调用具体的授权管理器进行授权
AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, mi);
// 发布一个授权事件(AuthorizationDeniedEvent)
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, mi, decision);
// 没有授权
if (decision != null && !decision.isGranted()) {
// 抛出异常
throw new AccessDeniedException("Access Denied");
}
}
// 获取认证信息
private Authentication getAuthentication() {
Authentication authentication = this.securityContextHolderStrategy.get().getContext().getAuthentication();
if (authentication == null) {
throw new AuthenticationCredentialsNotFoundException("An Authentication object was not found in the SecurityContext");
}
return authentication;
}
private static <T> void noPublish(Supplier<Authentication> authentication, T object, AuthorizationDecision decision) {
}
}
// 方法拦截之后的授权管理器(@PostAuthorize注解)
public class AuthorizationManagerAfterMethodInterceptor implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
// SecurityContextHolderStrategy持久化策略
private Supplier<SecurityContextHolderStrategy> securityContextHolderStrategy = SecurityContextHolder::getContextHolderStrategy;
// 当前拦截器的切点,就是该注解对应的表达式匹配器
private final Pointcut pointcut;
// 授权管理器
private final AuthorizationManager<MethodInvocationResult> authorizationManager;
// 执行的顺序
private int order;
// 授权的事件分发器,默认不发布任何事件,可以自己设置
private AuthorizationEventPublisher eventPublisher = AuthorizationManagerAfterMethodInterceptor::noPublish;
public AuthorizationManagerAfterMethodInterceptor(Pointcut pointcut, AuthorizationManager<MethodInvocationResult> authorizationManager) {
this.pointcut = pointcut;
this.authorizationManager = authorizationManager;
}
// 创建处理@PostAuthorize注解的拦截器
public static AuthorizationManagerAfterMethodInterceptor postAuthorize() {
return postAuthorize(new PostAuthorizeAuthorizationManager());
}
// 指定处理@PostAuthorize的授权管理器,并创建AuthorizationManagerAfterMethodInterceptor对象
public static AuthorizationManagerAfterMethodInterceptor postAuthorize(AuthorizationManager<MethodInvocationResult> authorizationManager) {
AuthorizationManagerAfterMethodInterceptor interceptor = new AuthorizationManagerAfterMethodInterceptor(AuthorizationMethodPointcuts.forAnnotations(PostAuthorize.class), authorizationManager);
interceptor.setOrder(500);
return interceptor;
}
// 执行当前拦截器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 放行,获取执行结果
Object result = mi.proceed();
// 尝试授权操作
this.attemptAuthorization(mi, result);
return result;
}
// 获取通知,就是当前AuthorizationManagerAfterMethodInterceptor拦截器对象
@Override
public Advice getAdvice() {
return this;
}
// 尝试授权操作
private void attemptAuthorization(MethodInvocation mi, Object result) {
// 将结果包装
MethodInvocationResult object = new MethodInvocationResult(mi, result);
// 获取到认证信息调用具体的授权管理器进行授权
AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, object);
// 发布一个授权事件(AuthorizationDeniedEvent)
this.eventPublisher.publishAuthorizationEvent(this::getAuthentication, object, decision);
// 没有授权,抛出异常
if (decision != null && !decision.isGranted()) {
throw new AccessDeniedException("Access Denied");
}
}
// 获取认证信息
private Authentication getAuthentication() {
Authentication authentication = this.securityContextHolderStrategy.get().getContext().getAuthentication();
if (authentication == null) {
throw new AuthenticationCredentialsNotFoundException("An Authentication object was not found in the SecurityContext");
}
return authentication;
}
private static <T> void noPublish(Supplier<Authentication> authentication, T object, AuthorizationDecision decision) {
}
}
// 方法拦截之后过滤的的授权管理器(@PostFilter注解)
public class PostFilterAuthorizationMethodInterceptor implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
// 获取SecurityContextHolder策略
private Supplier<SecurityContextHolderStrategy> securityContextHolderStrategy = SecurityContextHolder::getContextHolderStrategy;
// @PostFilter注解表达式的属性注册表
private PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry();
// 当前拦截器的切点,就是该注解对应的表达式匹配器
private final Pointcut pointcut;
public PostFilterAuthorizationMethodInterceptor() {
this.pointcut = AuthorizationMethodPointcuts.forAnnotations(PostFilter.class);
}
// 设置表达式处理器
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
this.registry = new PostFilterExpressionAttributeRegistry(expressionHandler);
}
// 获取当前切点
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this;
}
// 执行拦截器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 放行执行目标方法
Object returnedObject = mi.proceed();
// 获取表达式属性值
ExpressionAttribute attribute = this.registry.getAttribute(mi);
// 没有获取到表达式属性,不处理
if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) {
return returnedObject;
}
// 获取到处理@PostFilter注解的表达式处理器
DefaultMethodSecurityExpressionHandler expressionHandler = this.registry.getExpressionHandler();
// 创建表达式计算的上下文对象
EvaluationContext ctx = expressionHandler.createEvaluationContext(this::getAuthentication, mi);
// 将返回结果进行过滤
return expressionHandler.filter(returnedObject, attribute.getExpression(), ctx);
}
// 获取认证信息
private Authentication getAuthentication() {
Authentication authentication = this.securityContextHolderStrategy.get().getContext().getAuthentication();
if (authentication == null) {
throw new AuthenticationCredentialsNotFoundException("An Authentication object was not found in the SecurityContext");
}
return authentication;
}
}
// 方法拦截之前过滤的的授权管理器(@PreFilter注解)
public class PreFilterAuthorizationMethodInterceptor implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
// 获取SecurityContextHolder策略
private Supplier<SecurityContextHolderStrategy> securityContextHolderStrategy = SecurityContextHolder::getContextHolderStrategy;
// @PostFilter注解表达式的属性注册表
private PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry();
// 当前拦截器的切点,就是该注解对应的表达式匹配器
private final Pointcut pointcut;
public PreFilterAuthorizationMethodInterceptor() {
this.pointcut = AuthorizationMethodPointcuts.forAnnotations(PreFilter.class);
}
// 设置表达式处理器
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
this.registry = new PreFilterExpressionAttributeRegistry(expressionHandler);
}
// 获取切点
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
// 获取当前通知拦截器
@Override
public Advice getAdvice() {
return this;
}
// 执行拦截器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 获取注解的属性值的表达式
PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute attribute = this.registry.getAttribute(mi);
// 如果没有获取的属性,直接放行
if (attribute == PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute.NULL_ATTRIBUTE) {
return mi.proceed();
}
// 获取方法注解的表达式处理器
DefaultMethodSecurityExpressionHandler expressionHandler = this.registry.getExpressionHandler();
// 创建表达式的计算上下文对象
EvaluationContext ctx = expressionHandler.createEvaluationContext(this::getAuthentication, mi);
// 查找需要过滤的目标参数对象
Object filterTarget = this.findFilterTarget(attribute.getFilterTarget(), ctx, mi);
// 根据表达式进行过滤
expressionHandler.filter(filterTarget, attribute.getExpression(), ctx);
// 放行继续执行下一个拦截器
return mi.proceed();
}
/**
* 查找需要过滤的目标对象,方法存在多个参数必须加filterTargetName,否则只能有一个参数,并且不能是数组
*
* @param filterTargetName 指定的参数名称
* @param ctx 计算上下文对象
* @param methodInvocation 方法的执行对象
* @return 需要过滤的目标参数对象
*/
private Object findFilterTarget(String filterTargetName, EvaluationContext ctx, MethodInvocation methodInvocation) {
Object filterTarget;
// 如果给定了目标参数对象的名称
if (StringUtils.hasText(filterTargetName)) {
// 根据从上下文中通过变量名获取目标对象
filterTarget = ctx.lookupVariable(filterTargetName);
} else {
// 获取方法的所有参数
Object[] arguments = methodInvocation.getArguments();
// 参数必须只有一个
Assert.state(arguments.length == 1, "Unable to determine the method argument for filtering. Specify the filter target.");
// 获取到第一个参数对象
filterTarget = arguments[0];
// 并且不能为null
Assert.notNull(filterTarget, "Filter target was null. Make sure you passing the correct value in the method argument.");
}
// @Pre只可变的集合,不支持数组
Assert.state(!filterTarget.getClass().isArray(), "Pre-filtering on array types is not supported. Using a Collection will solve this problem.");
return filterTarget;
}
// 获取认证信息
private Authentication getAuthentication() {
Authentication authentication = this.securityContextHolderStrategy.get().getContext().getAuthentication();
if (authentication == null) {
throw new AuthenticationCredentialsNotFoundException("An Authentication object was not found in the SecurityContext");
}
return authentication;
}
}
// 处理@PostAuthorize注解的授权管理器
public class PostAuthorizeAuthorizationManager implements AuthorizationManager<MethodInvocationResult> {
// @PostAuthorize注解属性的注册表
private PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry();
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
this.registry = new PostAuthorizeExpressionAttributeRegistry(expressionHandler);
}
// 权限校验
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocationResult mi) {
// 获取注解表达式属性
ExpressionAttribute attribute = this.registry.getAttribute(mi.getMethodInvocation());
// 不存在属性表达式,不处理
if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) {
return null;
}
// 获取注解表达式处理器
DefaultMethodSecurityExpressionHandler expressionHandler = this.registry.getExpressionHandler();
// 创建计算上下文对象
EvaluationContext ctx = expressionHandler.createEvaluationContext(authentication, mi.getMethodInvocation());
// 设置返回值对象
expressionHandler.setReturnObject(mi.getResult(), ctx);
// 计算注解的表达式
boolean granted = ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx);
// 如果表达式为true,则授权成功,否则授权失败
return new ExpressionAuthorizationDecision(granted, attribute.getExpression());
}
}
// 处理@Secured注解的授权管理器
public final class SecuredAuthorizationManager implements AuthorizationManager<MethodInvocation> {
// 授权管理器,基于权限列表的授权管理器
private AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
// 缓存的权限信息
private final Map<MethodClassKey, Set<String>> cachedAuthorities = new ConcurrentHashMap<>();
// 设置授权管理器
public void setAuthoritiesAuthorizationManager(AuthorizationManager<Collection<String>> authoritiesAuthorizationManager) {
this.authoritiesAuthorizationManager = authoritiesAuthorizationManager;
}
// 授权校验
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
// 获取注解中写的权限列表
Set<String> authorities = this.getAuthorities(mi);
// 如果未填写,返回null,就不会处理
// 如果添加了,使用权限列表的授权管理器进行权限校验,返回授权管理器的校验结果
return authorities.isEmpty() ? null : this.authoritiesAuthorizationManager.check(authentication, authorities);
}
// 获取注解中写的权限列表
private Set<String> getAuthorities(MethodInvocation methodInvocation) {
Method method = methodInvocation.getMethod();
Object target = methodInvocation.getThis();
Class<?> targetClass = (target != null) ? target.getClass() : null;
// 创建缓存Key
MethodClassKey cacheKey = new MethodClassKey(method, targetClass);
// 缓存解析到的注解中的权限信息
return this.cachedAuthorities.computeIfAbsent(cacheKey, (k) -> this.resolveAuthorities(method, targetClass));
}
// 解析注解中的权限信息
private Set<String> resolveAuthorities(Method method, Class<?> targetClass) {
// 获取到目标方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 获取方法或者类中的@Secured注解
Secured secured = this.findSecuredAnnotation(specificMethod);
// 如果存在@Secured注解,获取标注了@注解中添加的权限列表
return (secured != null) ? Set.of(secured.value()) : Collections.emptySet();
}
// 获取方法或者类中的@Secured注解
private Secured findSecuredAnnotation(Method method) {
Secured secured = AuthorizationAnnotationUtils.findUniqueAnnotation(method, Secured.class);
return (secured != null) ? secured : AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), Secured.class);
}
}
// 处理@PreAuthorize注解的授权管理器
public class PreAuthorizeAuthorizationManager implements AuthorizationManager<MethodInvocation> {
// PreAuthorize注解属性的注册表
private PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry();
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
this.registry = new PreAuthorizeExpressionAttributeRegistry(expressionHandler);
}
// 权限校验
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
// 获取注解表达式属性
ExpressionAttribute attribute = this.registry.getAttribute(mi);
// 不存在属性表达式,不处理
if (attribute == ExpressionAttribute.NULL_ATTRIBUTE) {
return null;
}
// 创建计算上下文对象
EvaluationContext ctx = this.registry.getExpressionHandler().createEvaluationContext(authentication, mi);
// 计算注解的表达式
boolean granted = ExpressionUtils.evaluateAsBoolean(attribute.getExpression(), ctx);
// 如果表达式为true,则授权成功,否则授权失败
return new ExpressionAuthorizationDecision(granted, attribute.getExpression());
}
}
// 处理@DenyAll,@PermitAll,@RolesAllowed注解的授权管理器
public final class Jsr250AuthorizationManager implements AuthorizationManager<MethodInvocation> {
// JSR250包含的授权注解
private static final Set<Class<? extends Annotation>> JSR250_ANNOTATIONS = new HashSet<>();
static {
JSR250_ANNOTATIONS.add(DenyAll.class);
JSR250_ANNOTATIONS.add(PermitAll.class);
JSR250_ANNOTATIONS.add(RolesAllowed.class);
}
// 注解授权管理器的注册表
private final Jsr250AuthorizationManagerRegistry registry = new Jsr250AuthorizationManagerRegistry();
// 角色前缀
private String rolePrefix = "ROLE_";
// 设置角色前缀
public void setRolePrefix(String rolePrefix) {
this.rolePrefix = rolePrefix;
}
// 授权操作
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation methodInvocation) {
// 获取对应注解的授权管理器
AuthorizationManager<MethodInvocation> delegate = this.registry.getManager(methodInvocation);
/**
* {@link Jsr250AuthorizationManager.Jsr250AuthorizationManagerRegistry#resolveManager}
* 该check直接就是返回在resolveManager已经处理过的结果
*/
return delegate.check(authentication, methodInvocation);
}
// Jsr250注解的授权管理器注册表,该类是用于处理Jsr250注解逻辑,最终返回指定结果的授权管理器
private final class Jsr250AuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry {
// 获取授权管理器
public AuthorizationManager<MethodInvocation> getManager(MethodInvocation methodInvocation) {
Method method = methodInvocation.getMethod();
Object target = methodInvocation.getThis();
Class<?> targetClass = (target != null) ? target.getClass() : null;
// 生成缓存KEY
MethodClassKey cacheKey = new MethodClassKey(method, targetClass);
// 解析注解并返回指定结果的授权管理器,并缓存
return this.cachedManagers.computeIfAbsent(cacheKey, (k) -> resolveManager(method, targetClass));
}
// 解析注解信息,返回具有指定结果的授权管理器
@NonNull
@Override
public AuthorizationManager<MethodInvocation> resolveManager(Method method, Class<?> targetClass) {
// 查找授权注解信息
Annotation annotation = findJsr250Annotation(method, targetClass);
// 如果是DenyAll,表示拒绝所有,直接不授权就完成
if (annotation instanceof DenyAll) {
return (a, o) -> new AuthorizationDecision(false);
}
// 如果是PermitAll,表示允许所有,直接授权
if (annotation instanceof PermitAll) {
return (a, o) -> new AuthorizationDecision(true);
}
// 如果是RolesAllowed,表示允许注解中权限列表的任意一个即有权限
if (annotation instanceof RolesAllowed) {
RolesAllowed rolesAllowed = (RolesAllowed) annotation;
// 调用AuthorityAuthorizationManager的权限管理器进行校验,返回最终的结果
/**针对所有权限的授权管理器,内部代理了基于权限列表{@link AuthoritiesAuthorizationManager授权管理器*/
return AuthorityAuthorizationManager.hasAnyRole(Jsr250AuthorizationManager.this.rolePrefix, rolesAllowed.value());
}
// 如果不是以上的三个注解,返回一个空AuthorizationDecision
return NULL_MANAGER;
}
// 查找类或者方法中的Jsr250注解信息
private Annotation findJsr250Annotation(Method method, Class<?> targetClass) {
// 获取到目标方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 获取方法中的授权注解
Annotation annotation = findAnnotation(specificMethod);
// 如果方法中不存在注解,在获取类中的授权注解,如果都不存在返回null,否则返回注解信息
return (annotation != null) ? annotation : findAnnotation(specificMethod.getDeclaringClass());
}
// 查找方法或者类上的JSR250的授权注解
private Annotation findAnnotation(AnnotatedElement method) {
Set<Annotation> annotations = new HashSet<>();
for (Class<? extends Annotation> annotationClass : JSR250_ANNOTATIONS) {
// 先找方法中的,可以能存在多个,下面会校验,多个抛出异常
Annotation annotation = AuthorizationAnnotationUtils.findUniqueAnnotation(method, annotationClass);
if (annotation != null) {
annotations.add(annotation);
}
}
// 如果没有找到,直接返回null
if (annotations.isEmpty()) {
return null;
}
// 如果找到了多个,抛出异常
if (annotations.size() > 1) {
throw new AnnotationConfigurationException("The JSR-250 specification disallows DenyAll, PermitAll, and RolesAllowed from appearing on the same method.");
}
// 返回唯一的授权注解
return annotations.iterator().next();
}
}
}
// 针对所有权限的授权管理器,内部代理了基于权限列表授权管理器
public final class AuthorityAuthorizationManager<T> implements AuthorizationManager<T> {
// 角色前缀
private static final String ROLE_PREFIX = "ROLE_";
// 代理的基于权限列表授权管理器
private final AuthoritiesAuthorizationManager delegate = new AuthoritiesAuthorizationManager();
// 需要校验的权限列表
private final Set<String> authorities;
private AuthorityAuthorizationManager(String... authorities) {
this.authorities = Set.of(authorities);
}
// 设置角色的层次结构处理器
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
this.delegate.setRoleHierarchy(roleHierarchy);
}
// 校验是否存在指定角色
public static <T> AuthorityAuthorizationManager<T> hasRole(String role) {
// 角色名称不能以ROLE_开头,否则报错
Assert.isTrue(!role.startsWith(ROLE_PREFIX), () -> role + " should not start with " + ROLE_PREFIX + " since " + ROLE_PREFIX + " is automatically prepended when using hasRole. Consider using hasAuthority instead.");
// 拼接角色前缀判断权限
return hasAuthority(ROLE_PREFIX + role);
}
// 是否有权限
public static <T> AuthorityAuthorizationManager<T> hasAuthority(String authority) {
return new AuthorityAuthorizationManager<>(authority);
}
// 是有有给定的角色列表中的任意权限
public static <T> AuthorityAuthorizationManager<T> hasAnyRole(String... roles) {
return hasAnyRole(ROLE_PREFIX, roles);
}
// 是有有给定的权限列表中的任意角色
public static <T> AuthorityAuthorizationManager<T> hasAnyRole(String rolePrefix, String[] roles) {
return hasAnyAuthority(toNamedRolesArray(rolePrefix, roles));
}
// 是有有给定的权限列表中的任意权限
public static <T> AuthorityAuthorizationManager<T> hasAnyAuthority(String... authorities) {
return new AuthorityAuthorizationManager<>(authorities);
}
// 将所有给定的角色添加角色前缀,在进行校验
private static String[] toNamedRolesArray(String rolePrefix, String[] roles) {
String[] result = new String[roles.length];
for (int i = 0; i < roles.length; i++) {
String role = roles[i];
Assert.isTrue(rolePrefix.isEmpty() || !role.startsWith(rolePrefix), () -> role + " should not start with "
+ rolePrefix + " since " + rolePrefix
+ " is automatically prepended when using hasAnyRole. Consider using hasAnyAuthority instead.");
result[i] = rolePrefix + role;
}
return result;
}
// 权限校验,调用代理的基于权限列表授权管理器进行权限校验
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
return this.delegate.check(authentication, this.authorities);
}
}
// 基于权限列表的权限管理器
public final class AuthoritiesAuthorizationManager implements AuthorizationManager<Collection<String>> {
// 默认的角色层次结构处理器为给定权限列表原样返回
// 获得认证用户的所有可访问的授予权限,其中包含角色的层次结构,例如 ADMIN > USER > sys:user:list
// 默认的roleHierarchy实现是不经过任何加工返回指定的权限
// 如果提供了roleHierarchy,则返回经过加工之后的权限列表
private RoleHierarchy roleHierarchy = new NullRoleHierarchy();
// 设置指定的角色层次结构处理器
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "roleHierarchy cannot be null");
this.roleHierarchy = roleHierarchy;
}
// 授权校验
@Override
public AuthorityAuthorizationDecision check(Supplier<Authentication> authentication, Collection<String> authorities) {
// 判断当前认证用户是否有权限
boolean granted = this.isGranted(authentication.get(), authorities);
// 返回权限的决策信息
return new AuthorityAuthorizationDecision(granted, AuthorityUtils.createAuthorityList(authorities));
}
// 是否有权限
private boolean isGranted(Authentication authentication, Collection<String> authorities) {
// 如果认证了,并且被授权了,只要认证的用户具有注解中标注的权限列表中的任意一个则有权限
return authentication != null && this.isAuthorized(authentication, authorities);
}
// 是否被授权了,只要认证的用户具有注解中标注的权限列表中的任意一个则有权限
private boolean isAuthorized(Authentication authentication, Collection<String> authorities) {
// 获得认证用户的所有可访问的授予权限,其中包含角色的层次结构,例如 ADMIN > USER > sys:user:list
// 默认的roleHierarchy实现是不经过任何加工返回指定的权限
// 如果提供了roleHierarchy,则返回经过加工之后的权限列表
Collection<? extends GrantedAuthority> grantedAuthorities = this.getGrantedAuthorities(authentication);
// 遍历处理之后用户认证的角色列表
for (GrantedAuthority grantedAuthority : grantedAuthorities) {
// 与注解中写的权限列表进行意义比较,如果有一个包含,那么直接返回true,表示有权限
// 因此@Secured注解中的权限列表式OR的关系,只要存在一个即有权限
if (authorities.contains(grantedAuthority.getAuthority())) {
return true;
}
}
return false;
}
// 获得认证用户的所有可访问的授予权限,其中包含角色的层次结构,例如 ADMIN > USER > sys:user:list
// 默认的roleHierarchy实现是不经过任何加工返回指定的权限
// 如果提供了roleHierarchy,则返回经过加工之后的权限列表
private Collection<? extends GrantedAuthority> getGrantedAuthorities(Authentication authentication) {
return this.roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
}
}
相关推荐
【网络安全】缓存配置错误导致授权绕过
在普通用户身份下,我能够获取到该商店的所有订单信息,包括客户详情。
Spring官宣新家族成员:Spring Authorization Server
其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。// 以下两个bean 定义 生成jwt 的配置,可以直接参考文末源码介绍,这里就不在截图。(img-BcBkyYnm-1712112854021)]通过以上配置即可搭建完成 SAS 服务端,我们以授权码模式测试。
别再硬编码了!WinCC子画面动态加载的5种C脚本写法对比
本文深入解析WinCC子画面动态加载的5种C脚本实现方案,包括基础加载、路径动态解析、多语言切换、窗口自适应布局和混合架构交互。通过代码示例和场景分析,帮助开发者避免硬编码问题,提升工业自动化系统的交互效率和可维护性。特别推荐路径动态解析方案,有效解决项目路径管理的痛点。
基于注解的Spring Security原理解析
概述:Spring Security就是引入了一系列的SecurityFilter,将其添加到Spring中去了;在有请求时,根据URL是否符合每个Filter的规则来判断是否需要该Filter来进行处理。
android11-修改屏幕显示方向和触摸方向
参数0表示12点钟方向显示参数90表示3点钟方向显示参数180表示6点钟方向显示参数270表示9点钟方向显示。
机器人运动不流畅?手把手教你用ACCSET调整ABB/FANUC点位加速度
本文针对ABB和FANUC工业机器人运动不流畅、拐角抖动、到位震颤等常见问题,提供了详细的解决方案。核心在于使用ACCSET指令(ABB)或ACC选项(FANUC)调整机器人的点位加速度与减速度参数。文章通过实战案例与系统化调试流程,手把手指导工程师优化运动性能,实现平稳、精准的机器人运动控制。
Spring Authorization Server (二)配置分离优化
上一节我们配置启动了 Spring Authorization Server ,当时我们使用的大部分是默认配置,并且所有的配置都在一个配置文件中,接下来将 Spring Security 的配置和 Spring Authorization 的配置分离,并且创建一些工具类。
西安交通大学SQ轴承数据集(文末附数据)
西安交通大学SQ轴承数据集
Spring Security源码(一):整体框架设计
整个框架的核心就是构建一个名字为 springSecurityFilterChain 的过滤器,它的类型是 FilterChainProxy
2026 年 3 月青少年软编等考 C/C++ 三级测试题解析
摘要 本文包含三部分内容: 单选题(10题):考察C++基础语法和数据结构知识,涉及vector、栈、队列的操作和特性。 判断题(10题):测试对动态数组、栈、队列、字符串操作的理解,包括内存管理、访问方式和函数返回值等。 编程题(1题):模拟火车站售票窗口排队场景,要求根据输入输出各窗口的排队情况,重点考查队列的实际应用和边界条件处理。 答案解析详细,涵盖常见编程考点,适合检验基础知识的掌握程度。
CAN(2)-GD32
GD32中CAN的特征。
Spring Security
4.一旦用户提供了有效的凭据,Spring Security 将验证这些凭据,并创建一个已认证的安全上下文(SecurityContext)对象。Spring Security 是一个基于 Spring 框架的安全框架,提供了完整的安全解决方案,包括认证、7.如果用户有权访问资源,Spring Security 将允许用户访问资源,否则将返回一个错误信息。6.在接下来的请求中,Spring Security 将使用已经认证的安全上下文对象来判断用户是否有。我们不需要了解其框架。
C#实现Socket通信同时监听多客户端(附完整源码)
C#实现Socket通信同时监听多客户端(附完整源码)
SpringSecurity(Authorization Events)
对于每个被拒绝的授权,都会激发一个 AuthorizationDeniedEvent。此外,还可以为授予的授权激发 AuthorizationGrantedEvent。若要侦听这些事件,必须首先发布 AuthorizationEventPublisher。Spring Security 的 SpringAuthorizationEventPublisher 可能会做得很好。
如何在多 GPU 配置上运行 Unsloth:数据并行或模型并行
当工作负载受限于内存(模型或批次无法放入单张显卡)、或受限于计算且计算与通信比率较高时(即每块 GPU 的额外计算量超过同步参数的开销,如在 DDP 中,或超过传递激活值的开销,如在模型并行中),多 GPU 配置才开始显现优势。在松散连接的显卡上(尤其是 PCIe 版本的 H100 或 A100),额外的设备间数据传输会导致性能显著低于单 GPU 运行。让我们厘清概念,明确说明如何通过模型并行(将模型拆分到多个 GPU)或数据并行(在每个 GPU 上复制模型)来跨多 GPU 运行 Unsloth。
SAP B1中文培訓教材_SDK
公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说
springsecurity开启方法级的授权源码分析
至于 @PreAuthorize 注解的拦截器是如何生效的那就要靠 @EnableMethodSecurity 注解,因为该注解中导入了 @Import({MethodSecuritySelector.class}) 并接入到了IOC容器,因此只需要看 MethodSecuritySelector 类具体是怎么处理方法级的认证的即可。使用了方法权限注解开启了方法级的权限鉴定之后,就可以使用如下注解直接在控制器上使用方法级的权限鉴定了。处理器,其中的这部分源码解释可以看出如何使用表达式的过程。
LinePhone3.2.7(android端最新版本) sip客户端
SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/
Spring Security 源码解读:权限控制
本文样例代码地址:。本文使用Spring Boot 2.7.4版本,对应Spring Security 5.7.3版本。
pscad IEEE标准系统搭建说明
pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。
SpringSecurity系列——访问控制之基于方法的控制day6-3(源于官网5.7.2版本)
SpringSecurity的@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter提供了丰富的基于表达式的支持。如果您需要自定义处理表达式的方式,您可以公开一个自定义MethodSecurityExpressionHandler,就像这样}}方法授权是方法前授权和方法后授权的组合。方法前授权是在调用方法之前执行的。}}}...
Spring Security怎么给你授权的(二)
目前在Spring Boot中基于方法的权限管理主要是通过注解来实现,我们需要通过:开启Spring Security提供的四个权限注解,以及@PreFilter,这四个注解支持权限表达式,功能比较丰富。:开启Spring Security提供的@Secured注解,该注解不支持权限表达式。:开启JSR-250提供的注解,主要包括@DenyAll@PermitAll以及三个注解,这些注解也不支持权限表达式。:在目标方法执行之后进行权限校验。:在目标方法执行之后对方法的返回结果进行过滤。
【Spring-Security源码分析】Spring Security基于注解认证原理
1、开启注解功能 Spring Security默认是禁用注解的,要想开启注解功能需要在@Configuration类上加入@EnableMethodSecurity注解来判断用户对某个控制层的方法是否具有访问权限。 @Configuration @EnableGlobalMethodSecurity(prePostEnabled =true) public class WebSecurit...
Spring常用注解
Spring常用注解
Method Security
支持表达式的注解 Spring Security中定义了四个支持使用表达式的注解,分别是@PreAuthorize、@PostAuthorize、@PreFilter和@PostFilter。其中前两者可以用来在方法调用前或者调用后进行权限检查,后两者可以用来对集合类型的参数或者返回值进行过滤。要使它们的定义能够对我们的方法的调用产生影响我们需要设置global-method-sec...
spring中 EventPublisher
作用 这个其实就是一个设计模式中的观察者模式,广播推送消息 spring中怎么用? 客户端发布事件 public class IOCTest_Ext { @Test public void test01(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicatio...
springSecurity安全框架的学习和原理解读
转 springSecurity安全框架的学习和原理解读 标签: java springsecurity 更多 最近在公司的项目中使用了spring security框架,所以有机会来学习一下,公司的项目是使用springboot搭建 springBoot版本1.59 spring security 版本4.2.3 (个人理解可能会有偏差,希望有不正确之处,大家能够指出来,共同探讨交流。) 目录...
【项目推荐】基于 SpringBoot3 + Spring AI 的游泳馆管理系统:Agent + RAG + Function Calling 一次学全
它不是玩具 Demo,而是一个「业务 + AI」双主线交织的真实系统——预约业务在跑,AI 客服在旁边实时查库作答,两条线通过 Function Calling、RAG、站内消息串成一体。面试官问「你做过什么 AI 项目」时,你能从业务场景讲到架构取舍,从 RAG 切分参数讲到降级兜底——这和「我调了一下 ChatGPT 的 API」是完全不同的两个段位。项目已包含完整的建表 SQL、初始化数据、部署文档,克隆下来就能跑。获取方式:见文末说明 / 后台回复关键词获取。—— 完 ——
Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用
由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。
1981



被折叠的 条评论
为什么被折叠?



