当前我正在使用spring security和@PreAuthorize
注释来保护方法调用。现在我想改变一个方法调用的认证标记,就像Spring安全允许我做的run-as authentication replacement一样。用spring-security更改方法调用的安全上下文
我可以在每个方法基础上配置替换吗?每注释,SpEL表达式.... 如果没有,是否有可能在runAsManager中计算出哪种方法被调用? 我将如何配置安全对象的安全配置属性?
当前我正在使用spring security和@PreAuthorize
注释来保护方法调用。现在我想改变一个方法调用的认证标记,就像Spring安全允许我做的run-as authentication replacement一样。用spring-security更改方法调用的安全上下文
我可以在每个方法基础上配置替换吗?每注释,SpEL表达式.... 如果没有,是否有可能在runAsManager中计算出哪种方法被调用? 我将如何配置安全对象的安全配置属性?
我通过实现我自己的RunAsManager
解决了这个问题,它检查被调用方法上的自定义注释并返回相应的令牌。
很好用。
我已经发布a detailed article实施运行与@PreAuthorize
结合。
1)实现您自己的RunAsManager
,创建Authentication
以在基于任何自定义逻辑的方法执行期间使用。下面的示例使用自定义注释提供额外的角色:
public class AnnotationDrivenRunAsManager extends RunAsManagerImpl {
@Override
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if(!(object instanceof ReflectiveMethodInvocation) || ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class) == null) {
return super.buildRunAs(authentication, object, attributes);
}
String roleName = ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class).value();
if (roleName == null || roleName.isEmpty()) {
return null;
}
GrantedAuthority runAsAuthority = new SimpleGrantedAuthority(roleName);
List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
// Add existing authorities
newAuthorities.addAll(authentication.getAuthorities());
// Add the new run-as authority
newAuthorities.add(runAsAuthority);
return new RunAsUserToken(getKey(), authentication.getPrincipal(), authentication.getCredentials(),
newAuthorities, authentication.getClass());
}
}
此实现将寻找一个自定义@RunAsRole
标注在受保护的方法(如@RunAsRole("ROLE_AUDITOR")
),如有发现,将添加特定机构(ROLE_AUDITOR
在本案)列入授权机构名单。 RunAsRole
本身只是一个简单的自定义注释。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunAsRole {
String value();
}
2)实例化管理器:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_key"/>
</bean>
3)注册它:
<global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager">
<expression-handler ref="expressionHandler"/>
</global-method-security>
4)实施例的使用在控制器:
@Controller
public class TransactionLogController {
@PreAuthorize("hasRole('ROLE_REGISTERED_USER')") //Authority needed to access the method
@RunAsRole("ROLE_AUDITOR") //Authority added by RunAsManager
@RequestMapping(value = "/transactions", method = RequestMethod.GET) //Spring MVC configuration. Not related to security
@ResponseBody //Spring MVC configuration. Not related to security
public List<Transaction> getTransactionLog(...) {
... //Invoke something in the backend requiring ROLE_AUDITOR
{
... //User does not have ROLE_AUDITOR here
}
编辑: 在RunAsManagerImpl
中的值可以是任何你想要的。下面是Spring docs其使用的摘录:
为了确保恶意代码不会创建一个关键的
RunAsUserToken
和现在 它保证接受的RunAsImplAuthenticationProvider
, 散列被存储在所有生成的标记。该RunAsManagerImpl
和RunAsImplAuthenticationProvider
在 豆上下文中创建具有相同的键:<bean id="runAsManager" class="org.springframework.security.access.intercept.RunAsManagerImpl">
<bean id="runAsAuthenticationProvider" class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
通过使用 相同的密钥,每个
RunAsUserToken
可以验证它的创建由 批准RunAsManagerImpl
。出于安全原因,创建 之后RunAsUserToken
是不可变的。
“my_run_as_key”的用途是什么? - 我无法弄清楚。我可能读过你在这里引用的同一个指南,但这个关键对我没有任何意义。 – 2016-12-12 11:07:39
@DanielBo值可以是任何你想要的。它基本上是一个密码。 我更新了为什么需要引用Spring文档的答案。 – kaqqao 2016-12-12 14:34:27