权限代码和名称的 Spring Security 表达式
Posted
技术标签:
【中文标题】权限代码和名称的 Spring Security 表达式【英文标题】:Spring Security expressions for permission code and name 【发布时间】:2017-02-11 07:47:49 【问题描述】:在我的 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 正确实现这一点?可能有一些预先构建的方法来实现这一点?
【问题讨论】:
【参考方案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;
【讨论】:
感谢您的回答。现在我有以下错误:无法从 AbstractSecurityExpressionHandler以上是关于权限代码和名称的 Spring Security 表达式的主要内容,如果未能解决你的问题,请参考以下文章