目前我正在使用 spring security 和@PreAuthorize
annotations 来保护方法调用。现在,我想更改方法调用的身份验证令牌,例如 spring-security 的run-as 身份验证替换允许我这样做。
我可以根据每个方法配置替换吗?每个注释,SpEL 表达式......如果没有,是否有可能在 runAsManager 中找出调用了什么方法?我将如何为安全对象配置安全配置属性?
目前我正在使用 spring security 和@PreAuthorize
annotations 来保护方法调用。现在,我想更改方法调用的身份验证令牌,例如 spring-security 的run-as 身份验证替换允许我这样做。
我可以根据每个方法配置替换吗?每个注释,SpEL 表达式......如果没有,是否有可能在 runAsManager 中找出调用了什么方法?我将如何为安全对象配置安全配置属性?
我已经发布了一篇关于结合@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
}
编辑:key
in
的值RunAsManagerImpl
可以是您想要的任何值。这是Spring 文档关于其使用的摘录:
为确保恶意代码不会创建
RunAsUserToken
并呈现它以保证接受RunAsImplAuthenticationProvider
,密钥的哈希存储在所有生成的令牌中。RunAsManagerImpl
andRunAsImplAuthenticationProvider
是在 bean 上下文中使用相同的键创建的:<bean id="runAsManager" class="org.springframework.security.access.intercept.RunAsManagerImpl">
<bean id="runAsAuthenticationProvider" class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
通过使用相同的密钥,
RunAsUserToken
可以验证每个密钥都是由已批准的RunAsManagerImpl
.RunAsUserToken
出于安全原因,它在创建后是不可变的。
我通过实现自己的方法来解决这个问题,RunAsManager
该方法检查调用方法上的自定义注释并返回适当的令牌。
效果很好。