如何从一个端口
<sec:global-method-security secured-annotations="disabled">
<sec:protect-pointcut expression='execution(* x.y.z.end*(..))' access='...' />
弹簧java-config
@EnableGlobalMethodSecurity
@Configuration
public class MyConfiguration extends WebSecurityConfigurerAdapter {
这里有一个类似的问题http://forum.spring.io/forum/spring-projects/security/726615-protect-pointcut-in-java-configuration
答案 0 :(得分:2)
有一个解决方法。安全点信息保存在MethodSecurityMetadataSource
实现中(然后由MethodInterceptor
使用),因此我们必须创建一个额外的MethodSecurityMetadataSource
。正如Spring论坛帖子中所提到的,xml切入点配置保存在MapBasedMethodSecurityMetadataSource
中并由ProtectPointcutPostProcessor
处理。我们还需要一个ProtectPointcutPostProcessor
的实例。不幸的是,这个类是final和package-private,所以有两个选项:
然后在您的上下文中创建以下bean:
@Bean
public Map<String, List<ConfigAttribute>> protectPointcutMap() {
Map<String, List<ConfigAttribute>> map = new HashMap<>();
// all the necessary rules go here
map.put("execution(* your.package.service.*Service.*(..))", SecurityConfig.createList("ROLE_A", "ROLE_B"));
return map;
}
@Bean
public MethodSecurityMetadataSource mappedMethodSecurityMetadataSource() {
// the key is not to provide the above map here. this class will be populated later by ProtectPointcutPostProcessor
return new MapBasedMethodSecurityMetadataSource();
}
// it's either the original spring bean created with reflection or your own copy of it
@Bean
public ProtectPointcutPostProcessor pointcutProcessor() {
ProtectPointcutPostProcessor pointcutProcessor = new ProtectPointcutPostProcessor((MapBasedMethodSecurityMetadataSource) mappedMethodSecurityMetadataSource());
pointcutProcessor.setPointcutMap(protectPointcutMap());
return pointcutProcessor;
}
我们已经创建了必要的bean,现在我们必须告诉spring使用它们。我假设您正在延长GlobalMethodSecurityConfiguration
。默认情况下,它会创建DelegatingMethodSecurityMetadataSource
,其中包含其他MethodSecurityMetadataSource
的列表。根据您想要实现的目标,您有以下选择:
如果要保留所有其他MethodSecurityMetadataSource
(如用于解析@Secured
注释的那些),可以通过覆盖以下方法来扩展委派元数据源中的列表:
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
它会将它注入列表中的第一位,但这可能会导致一些问题。
如果您想保留其他来源,但希望您的列表中的最后一个,则覆盖以下方法:
@Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
DelegatingMethodSecurityMetadataSource metadataSource = (DelegatingMethodSecurityMetadataSource) super.methodSecurityMetadataSource();
metadataSource.getMethodSecurityMetadataSources().add(mappedMethodSecurityMetadataSource());
return metadataSource;
}
如果您希望您的来源是唯一的(您不想使用@Secured
或任何其他注释),那么您可以覆盖相同的方法,只是使用不同的内容
@Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
答案 1 :(得分:1)
我关注了@marhewa的评论,并且能够通过定义以下bean来使用类ProtectPointcutPostProcessor
的Spring版本
/**
* Needed to use reflection because I couldn't find a way to instantiate a
* ProtectPointcutPostProcessor via a BeanFactory or ApplicationContext. This bean will process
* the AspectJ pointcut defined in the map; check all beans created by Spring; store the matches
* in the MapBasedMethodSecurityMetadataSource bean so Spring can use it during its checks
*
* @return
* @throws Exception
*/
@Bean(name = "protectPointcutPostProcessor")
Object protectPointcutPostProcessor() throws Exception {
Class<?> clazz =
Class.forName("org.springframework.security.config.method.ProtectPointcutPostProcessor");
Constructor<?> declaredConstructor =
clazz.getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
declaredConstructor.setAccessible(true);
Object instance = declaredConstructor.newInstance(pointcutMethodMetadataSource());
Method setPointcutMap = instance.getClass().getMethod("setPointcutMap", Map.class);
setPointcutMap.setAccessible(true);
setPointcutMap.invoke(instance, pointcuts());
return instance;
}
这样我就不需要复制这个Spring类的代码了。
干杯