你應該可以在沒有太多麻煩的情況下用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
不,我沒有遇到任何不能這樣做的事情。還有什麼可以保證的?靜態內容? –