java 自定义表达式_如何创建用于spring安全表达式语言注释的自定义方法

本文讨论如何在Spring安全中创建自定义方法以用于表达式语言注解,实现基于方法的授权。通过扩展`SecurityExpressionRoot`和自定义`MethodSecurityExpressionHandler`,可以添加自定义功能,如`@PreAuthorize("@mySecurityService.hasPermission('special')")`。文章提供了解决方案,包括在XML配置中设置自定义bean,并展示了如何在自定义安全服务中实现权限检查方法。
摘要由CSDN通过智能技术生成

问题

我想创建一个类,通过注释添加自定义方法以用于spring安全表达式语言,以进行基于方法的授权。

例如,我想创建一个像'customMethodReturningBoolean'这样的自定义方法,以某种方式使用:

@PreAuthorize("customMethodReturningBoolean()")

public void myMethodToSecure() {

// whatever

}

我的问题是这个。如果可能,我应该创建自定义方法的子类,我将如何在spring xml配置文件中配置它,并且有人给我一个以这​​种方式使用的自定义方法的示例?

#1 热门回答(152 赞)

所提到的技术都不会再起作用了。好像Spring已经花了很大力气来阻止用户覆盖SecurityExpressionRoot。

编辑11/19/14设置Spring使用安全注释:

...

像这样创建一个bean:

@Component("mySecurityService")

public class MySecurityService {

public boolean hasPermission(String key) {

return true;

}

}

然后在你的jsp中做这样的事情:

或者注释方法:

@PreAuthorize("@mySecurityService.hasPermission('special')")

public void doSpecialStuff() { ... }

请记住:如果你使用的是Spring,你必须通过扩展类,重写方法,实现接口等来解决问题......那么你可能做错了什么。它是所有注释和xml,这就是为什么我们如此喜欢Spring而不是(旧版本的)EJB。

此外,你可以在your@PreAuthorize注释中使用Spring Expression Language来访问当前身份验证以及方法参数。

例如:

@Component("mySecurityService")

public class MySecurityService {

public boolean hasPermission(Authentication authentication, String foo) { ... }

}

然后更新你的@PreAuthorize以匹配新方法签名:

@PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)")

public void doSpecialStuff(String foo) { ... }

#2 热门回答(32 赞)

你需要子类化两个类。

首先,设置一个新方法表达式处理程序

myMethodSecurityExpressionHandler将是DefaultMethodSecurityExpressionHandler的子类,覆盖createEvaluationContext(),在MethodSecurityEvaluationContext中设置子类MethodSecurityExpressionRoot。

例如:

@Override

public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {

MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);

MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth);

root.setTrustResolver(trustResolver);

root.setPermissionEvaluator(permissionEvaluator);

root.setRoleHierarchy(roleHierarchy);

ctx.setRootObject(root);

return ctx;

}

#3 热门回答(14 赞)

Thanksericacm,但由于以下几个原因它不起作用:

DefaultMethodSecurityExpressionHandler的属性是私有的(反射可见性kludges不合需要)

至少在我的Eclipse中,我无法解析MethodSecurityEvaluationContext对象

不同之处在于我们调用现有的createEvaluationContext方法,然后添加我们的自定义根对象。最后我刚刚返回anStandardEvaluationContextobject类型,因为MethodSecurityEvaluationContext无法在编译器中解析(它们都来自同一个接口)。这是我现在生产的代码。

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

// parent constructor

public CustomMethodSecurityExpressionHandler() {

super();

}

/**

* Custom override to use {@link CustomSecurityExpressionRoot}

*

* Uses a {@link MethodSecurityEvaluationContext} as the EvaluationContext implementation and

* configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.

*/

@Override

public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {

// due to private methods, call original method, then override it's root with ours

StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);

ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );

return ctx;

}

}

这将通过扩展SecurityExpressionRoot替换默认根。在这里,我将hasRole重命名为hasEntitlement:

public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {

// parent constructor

public CustomSecurityExpressionRoot(Authentication a) {

super(a);

}

/**

* Pass through to hasRole preserving Entitlement method naming convention

* @param expression

* @return boolean

*/

public boolean hasEntitlement(String expression) {

return hasRole(expression);

}

}

最后更新securityContext.xml(并确保它从applcationContext.xml引用):

jsr250-annotations="disabled"

secured-annotations="disabled"

pre-post-annotations="enabled">

注意:@Secured注释不会接受此覆盖,因为它通过不同的验证处理程序运行。所以,在上面的xml我禁用它们以防止以后混淆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值