1)首先,你必须重新实现
MethodSecurityexpressionRoot,其中包含额外的方法特定功能。最初的Spring Security实现是程序包私有的,因此不能仅对其进行扩展。我建议检查给定类的源代码。
public class CustomMethodSecurityexpressionRoot extends SecurityexpressionRoot implements MethodSecurityexpressionOperations { // copy everything from the original Spring Security MethodSecurityexpressionRoot // add your custom methods public boolean isAdmin() { // do whatever you need to do, e.g. delegate to other components // hint: you can here directly access Authentication object // via inherited authentication field } public boolean isOwner(Long id) { // do whatever you need to do, e.g. delegate to other components }}2)接下来,你必须实现
MethodSecurityexpressionHandler将使用上述定义的
custom CustomMethodSecurityexpressionRoot。
public class CustomMethodSecurityexpressionHandler extends DefaultMethodSecurityexpressionHandler { private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); @Override public void setReturnObject(Object returnObject, evaluationContext ctx) { ((MethodSecurityexpressionRoot) ctx.getRootObject().getValue()).setReturnObject(returnObject); } @Override protected MethodSecurityexpressionOperations createSecurityexpressionRoot(Authentication authentication, MethodInvocation invocation) { final CustomMethodSecurityexpressionRoot root = new CustomMethodSecurityexpressionRoot(authentication); root.setThis(invocation.getThis()); root.setPermissionevaluator(getPermissionevaluator()); root.setTrustResolver(this.trustResolver); root.setRoleHierarchy(getRoleHierarchy()); return root; }}3)在你的上下文中定义表达式处理程序bean,例如,通过XML,你可以按以下方式进行操作
<bean id="methodSecurityexpressionHandler" > <property name="roleHierarchy" ref="roleHierarchy" /> <property name="permissionevaluator" ref="permissionevaluator" /></bean>
4)注册上面定义的处理程序
<security:global-method-security pre-post-annotations="enabled"> <security:expression-handler ref="methodSecurityexpressionHandler"/></security:global-method-security>
5)然后在你的
@PreAuthorize和/或
@PostAuthorize注释中使用定义的表达式
@PreAuthorize("isAdmin() or isOwner(#id)")public void deleteGame(@PathVariable int id, @ModelAttribute currentGame) { // do whatever needed}还有一件事。使用方法级安全性来保护控制器方法不是很普遍,而是使用业务逻辑(也就是你的服务层方法)来保护方法不是很普遍。然后,你可以使用以下内容。
public interface GameService { // rest omitted @PreAuthorize("principal.admin or #game.owner = principal.username") public void delete(@P("game") Game game);}但是请记住,这仅是示例。它期望实际的主体具有
isAdmin()方法,并且游戏具有
getOwner()返回所有者的用户名的方法。



