アノテーションをテストするためのサンプルクラスが@PreAuthorize
あります。これは多かれ少なかれ次のようになります。
class BankService {
@PreAuthorize("hasCustomRole('ROLE_CUSTOM') or hasRole('ROLE_EXAMPLE')")
Double getAccountBalance(Integer accountNumber) {
return 1234;
}
@PreAuthorize("#accountNumber > 400")
int getValue(Integer accountNumber) {
return 1234;
}
}
あなたは私が追加している注釈でhasCustomRole(String expression)
気付くことができます:@PreAuthorize
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
public CustomSecurityExpressionRoot(Authentication auth) {
super(auth);
}
public boolean hasCustomRole(String expression) {
return /* some magic */;
}
}
また、私はDefaultMethodSecurityExpressionHandler
次のように拡張しています:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
public CustomMethodSecurityExpressionHandler() {
super();
}
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject(new CustomSecurityExpressionRoot(auth));
return ctx;
}
}
結局、すべてが包まれていresources.groovy
ます:
beans = {
/* ... some stuff ... */
xmlns security:'http://www.springframework.org/schema/security'
security.'global-method-security'('pre-post-annotations': 'enabled') {
security.'expression-handler'(ref: 'expressionHandler')
}
expressionHandler(my.package.plugin.security.expression.CustomMethodSecurityExpressionHandler)
}
ここで、からセキュリティ部分を削除すると、resources.groovy
当然、hasCustomRole()
メソッドを使用できなくなりますが、次のように機能します。
assert bankService.getValue(500) == 1234
しかし、私が自分の実装を注入すると、前のステートメントは次のようになります。
Access is denied
org.springframework.security.access.AccessDeniedException: Access is denied
さらに調査した後、私はこれを見つけました:
prepost.PrePostAnnotationSecurityMetadataSource Looking for Pre/Post annotations for method 'getValue' on target class 'class my.package.plugin.security.test.BankService'
prepost.PrePostAnnotationSecurityMetadataSource @org.springframework.security.access.prepost.PreAuthorize(value=#accountNumber > 400) found on specific method: public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer)
method.DelegatingMethodSecurityMetadataSource Adding security method [CacheKey[my.package.plugin.security.test.BankService; public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer)]] with attributes [[authorize: '#accountNumber > 400', filter: 'null', filterTarget: 'null']]
aopalliance.MethodSecurityInterceptor Secure object: ReflectiveMethodInvocation: public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer); target is of class [my.package.plugin.security.test.BankService$$EnhancerByCGLIB$$c590f9ac]; Attributes: [[authorize: '#accountNumber > 400', filter: 'null', filterTarget: 'null']]
aopalliance.MethodSecurityInterceptor Previously Authenticated: org.springframework.security.authentication.TestingAuthenticationToken@b35bafc3: Principal: test; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_TELLER
method.MethodSecurityEvaluationContext Unable to resolve method parameter names for method: public final int my.package.plugin.security.test.BankService$$EnhancerByCGLIB$$c590f9ac.getValue(java.lang.Integer). Debug symbol information is required if you are using parameter names in expressions.
興味深い部分はですDebug symbol information is required if you are using parameter names in expressions.
。これは、クラスが変数名に関するデバッグ情報なしでコンパイルされることを示唆しています。しかし、自分のBeanを注入しなければ、すべてが正常に機能します。
デバッグ情報が欠落している理由と、それを修正する方法は何でしょうか。
これは、Grails 2.0.4用に開発されたGrailsプラグインであり、バージョン1.2.7.3のspring-security-coreプラグイン、バージョン1.1のspring-security-aclプラグイン、およびSpringSecurity3.0.7.RELEASEを使用しています。
編集:
この問題をさらに面白くするために、これは後で私が発見したものです。。を使用して.class
ファイルを調べると、「欠落している」デバッグ情報が実際に存在しますjavap
。したがって、クラスは正しくコンパイルされますが、Springはとにかく文句を言います...