在我的Spring Security项目中,我使用@PreAuthorize
注释保护了以下方法:
@PreAuthorize("hasAnyAuthority('PERMISSION_UPDATE_OWN_DECISION', 'PERMISSION_UPDATE_ANY_DECISION')")
@RequestMapping(value = "/{decisionId}/update", method = RequestMethod.POST)
public DecisionResponse updateDecision(@PathVariable @NotNull @DecimalMin("0") Long decisionId, @Valid @RequestBody UpdateDecisionRequest decisionRequest) {
....
}
我还将Spring OAuth2与JWT令牌一起使用,并将所有权限存储在此令牌内。现在,我使用相当长的权限名称,例如PERMISSION_UPDATE_OWN_DECISION
,并希望替换它们以显着减少JWT令牌大小(权限部分)。
其中一个想法是引入权限代码,例如:
1, PERMISSION_UPDATE_OWN_DECISION
2, PERMISSION_UPDATE_ANY_DECISION
其中1
是权限代码,PERMISSION_UPDATE_OWN_DECISION
是权限名称。
但我不想直接使用这些代码,因为它会降低我的代码的可读性,例如:
@PreAuthorize("hasAnyAuthority('1', '2')")
而不是我喜欢使用允许我根据真实权限名称检索此代码的内容,例如:
@PreAuthorize("hasAnyAuthority(getCode('PERMISSION_UPDATE_OWN_DECISION')), getCode('PERMISSION_UPDATE_ANY_DECISION'))")
如何使用Spring Security和Spring Security Expressions正确实现此功能?可能有一些预先建立的方法来实现这个目标吗?
答案 0 :(得分:1)
首先,您需要子类化MethodSecurityExpressionRoot
并使用您的逻辑创建自定义类。
public class CustomMethodSecurityExpressionRoot extends MethodSecurityExpressionRoot {
public boolean hasAnyAuthorityWithCodes(String... codes) {
String[] ids = // Your custom Logic to get Ids from Code
return hasAnyAuthority(ids);
}
}
然后子类DefaultMethodSecurityExpressionHandler
并覆盖它的createEvaluationContext
方法。
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
MethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(auth);
root.setTrustResolver(trustResolver);
root.setPermissionEvaluator(permissionEvaluator);
root.setRoleHierarchy(roleHierarchy);
ctx.setRootObject(root);
return ctx;
}
最后,您可以在配置中使用此自定义DefaultMethodSecurityExpressionHandler
<global-method-security>
<expression-handler ref="customMethodSecurityExpressionHandler"/>
</global-method-security>
并使用
@PreAuthorize("hasAnyAuthorityWithCodes('PERMISSION_UPDATE_OWN_DECISION','PERMISSION_UPDATE_ANY_DECISION')")
<强>更新强>
子类DefaultMethodSecurityExpressionHandler
并覆盖createSecurityExpressionRoot
方法
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, MethodInvocation invocation) {
MethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(
authentication);
root.setThis(invocation.getThis());
root.setTrustResolver(trustResolver);
root.setPermissionEvaluator(permissionEvaluator);
root.setRoleHierarchy(roleHierarchy);
root.setDefaultRolePrefix(defauleRolePrefix);
return root;
}