gpt4 book ai didi

java - 如何以编程方式向 Spring Bean 添加安全性

转载 作者:行者123 更新时间:2023-12-02 08:35:26 26 4
gpt4 key购买 nike

我正在使用 spring-security-tiger-2.0.5。

有没有办法以编程方式向 Spring Bean 添加安全代理?

我正在通过 BeanDefinitionBuilder 构建 bean,并且我想添加与 @Secured 注释相同的行为。

roleName 的 @Secured 等效项将作为参数传递。

最佳答案

要以编程方式将 Spring Security 功能注入(inject)现有 bean,您可能需要使用 Spring Security 应用程序上下文并在那里注册您的 bean:

@Test
public void testSpringSecurity() throws Exception {
InMemoryXmlApplicationContext ctx = initSpringAndSpringSecurity();

// Creates new instance
IMyService secured = (IMyService) ctx.getAutowireCapableBeanFactory()
.initializeBean(new MyService(), "myService");

assertTrue(AopUtils.isAopProxy(secured));

fakeSecurityContext("ROLE_USER");
secured.getCustomers(); // Works: @Secured("ROLE_USER")

fakeSecurityContext("ROLE_FOO");
try {
secured.getCustomers(); // Throws AccessDenied Exception
fail("AccessDeniedException expected");
} catch (AccessDeniedException expected) {
}
}

private InMemoryXmlApplicationContext initSpringAndSpringSecurity() {
InMemoryXmlApplicationContext ctx = new InMemoryXmlApplicationContext(
"<b:bean id='authenticationManager' class='org.springframework.security.MockAuthenticationManager' /> "
+ "<b:bean id='accessDecisionManager' class='org.springframework.security.vote.UnanimousBased'><b:property name='decisionVoters'><b:list><b:bean class='org.springframework.security.vote.RoleVoter'/></b:list></b:property></b:bean>"
+ "<b:bean id='objectDefinitionSource' class='org.springframework.security.annotation.SecuredMethodDefinitionSource' /> "
+ "<b:bean id='autoproxy' class='org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator'/>"
+ "<b:bean id='methodSecurityAdvisor' class='org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor' autowire='constructor'/>"
+ "<b:bean id='securityInterceptor' class='org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor'><b:property name='authenticationManager' ref='authenticationManager' /><b:property name='accessDecisionManager' ref='accessDecisionManager' /><b:property name='objectDefinitionSource' ref='objectDefinitionSource' /></b:bean>");
return ctx;
}

我使用了内存中应用程序上下文,正如 MethodDefinitionSourceAdvisor 在其文档中指出的那样,自动代理仅针对 ApplicationContext 启用。因此,我相信,如果您不为每个服务对象使用单独的 ProxyFactoryBean ,您需要一个用于自动代理的应用程序上下文。但由于您使用的是 @Secured 注释,我怀疑这与自动代理相同。

fakeSecurityContext() 只是将具有给定角色的 Authentication 对象设置到 SecurityContextHolder 中以进行测试。

您可以自己使用 Spring Core 功能来完成此操作。假设您有一项返回客户列表的服务,并且当前用户只能查看收入达到特定限制的客户。以下测试用例将是我们的开始:

@Test
public void testSecurity() throws Exception {
ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext(
"spring.xml");
IMyService service = (IMyService) appCtx.getBean("secured",
IMyService.class);
assertEquals(1, service.getCustomers().size());
}

这是原始服务实现:

public class MyService implements IMyService {

public List<Customer> getCustomers() {
return Arrays.asList(new Customer(100000), new Customer(5000));
}

}

spring.xml 中配置您的服务对象并添加方法拦截器:

<bean id="service" class="de.mhaller.spring.MyService"></bean>

<bean id="securityInterceptor" class="de.mhaller.spring.MyServiceInterceptor">
<property name="revenueLimit" value="50000"/>
</bean>

<bean id="secured" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="service" />
<property name="interceptorNames">
<list>
<value>securityInterceptor</value>
</list>
</property>
</bean>

安全拦截器实现:

public class MyServiceInterceptor implements MethodInterceptor {

private int revenueLimit = 10000;
public void setRevenueLimit(int revenueLimit) {
this.revenueLimit = revenueLimit;
}

@SuppressWarnings("unchecked")
public Object invoke(MethodInvocation mi) throws Throwable {
List<Customer> filtered = new ArrayList<Customer>();
List<Customer> result = (List<Customer>) mi.proceed();
for (Customer customer : result) {
if (customer.isRevenueBelow(revenueLimit)) {
filtered.add(customer);
}
}
return filtered;
}

}

使用这种方法的优点是,您不仅可以声明性地检查当前用户的角色,还可以动态地执行公司策略,例如根据业务值(value)限制返回的对象。

关于java - 如何以编程方式向 Spring Bean 添加安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1959272/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com