你应该可以在没有太多麻烦的情况下用spring security和grails来做到这一点。
我在过去使用了以下两种方法来完成类似的任务。两者都需要弹簧安全性ACL插件,它提供了@PreAuthorize
和@PostAuthorize
注释。
定制PermissionEvaluator
您可以使用安全注释中hasPermission()
方法和创建自定义PermissionEvaluator
。在这个代码看起来是这样的:
@PreAuthorize("hasPermission(#myObject, 'update')")
public void updateSomething(myObject) {
..
}
的hasPermission()
电话由弹簧安全路由到PermissionEvaluator
。为了编写自己的实现你要实现PermissionEvaluator
接口:
class MyPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
// your custom logic..
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
// your custom logic
}
}
要注册PermissionEvaluator
你必须重写名为expressionHandler
豆。您可以通过在conf/spring/resources.groovy
添加以下行做到这一点:
beans = {
expressionHandler(MyExpressionHandler) {
parameterNameDiscoverer = ref('parameterNameDiscoverer')
permissionEvaluator = ref('myPermissionEvaluator') // your PermissionEvaluator
roleHierarchy = ref('roleHierarchy')
trustResolver = ref('authenticationTrustResolver')
}
myPermissionEvaluator(MyPermissionEvaluator)
}
在resources.groovy
您可以定义豆类,就像您在使用applicationContext.xml
春天的时候做。以上几行创建了一个类型为MyPermissionEvaluator
的豆,豆名为myPermissionEvaluator
。 Spring证券expressionHandler
bean被一个类型为MyExpressionHandler
的bean所覆盖。其他依赖项是从spring security ACL插件的配置文件中复制的。
服务中的安全注解调用
如果的hasPermission()
方法的设计并不achive你的要求,你可以使用简单的服务调用来代替。 @PostAuthorize
和@PreAuthorize
注释使用SPEL来评估表达式。在SPEL内,您可以使用@
符号来访问bean。例如:
@PreAuthorize("@securityService.canAccess(#myObject)")
public void doSomething(myObject) {
..
}
此调用名为securityService
bean的canAccess
方法,并传递方法参数吧。
要使用此方法,您必须在EvaluationContext上注册BeanResolver。为此,您必须覆盖由spring security ACL插件配置的DefaultMethodSecurityExpressionHandler。
这可以如下所示:
class MyExpressionHandler extends DefaultMethodSecurityExpressionHandler {
BeanResolver beanResolver
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi)
ctx.setBeanResolver(beanResolver) // set BeanResolver here
return ctx;
}
}
BeanResolver
是一个简单的界面,解决了一个bean的名字命名的bean实例:
class GrailsBeanResolver implements BeanResolver {
GrailsApplication grailsApplication
@Override
public Object resolve(EvaluationContext evaluationContext, String beanName) throws AccessException {
return grailsApplication.mainContext.getBean(beanName)
}
}
最后豆子添加到resources.groovy
:
expressionHandler(MyExpressionHandler) {
parameterNameDiscoverer = ref('parameterNameDiscoverer')
permissionEvaluator = ref('permissionEvaluator')
roleHierarchy = ref('roleHierarchy')
trustResolver = ref('authenticationTrustResolver')
beanResolver = ref('beanResolver') // this is your BeanResolver
}
// This is the service called within security expressions
// If you place your service in the grails service folder you can skip this line
securityService(MySecurityService)
// this is your BeanResolver
beanResolver(GrailsBeanResolver) {
grailsApplication = ref('grailsApplication')
}
Updat e(2013-10-22):最近我写了一个blog post关于这个,它提供了一些额外的信息。
不知道这是最好的方式,但你谈论的安全性我通过过滤器完成。 –
感谢@JamesKleeh的回应,是否遇到任何问题只能过滤控制器操作? – mnd
不,我没有遇到任何不能这样做的事情。还有什么可以保证的?静态内容? –