从2.0开始Spring Security对服务层的方法的安全有了实质性的改善。他提供对JSR-250的注解安全支持象框架原生的@Secured注解一样好。从3.0开始你也可以使用新的基于表达式的注解。你可以应用安全到单独的bean,使用拦截方法元素去装饰Bean声明,或者你可以在整个服务层使用AspectJ风格的切入点保护多个bean。

EnableGlobalMethodSecurity

我们可以在任何使用@Configuration的实例上,使用@EnableGlobalMethodSecurity注解来启用基于注解的安全性。例如下面会启用Spring 的 @Secured注解.

@EnableGlobalMethodSecurity(securedEnabled = true) 
public class MethodSecurityConfig { 
// ... 
} 

添加一个注解到一个方法(或者一个类或者接机)会限制对相应方法的访问。Spring Security的原生注解支持定义了一套用于该方法的属性。这些将被传递到AccessDecisionManager 来做实际的决定:

public interface BankService { 

@Secured("IS_AUTHENTICATED_ANONYMOUSLY") 
public Account readAccount(Long id); 

@Secured("IS_AUTHENTICATED_ANONYMOUSLY") 
public Account[] findAccounts(); 

@Secured("ROLE_TELLER") 
public Account post(Account account, double amount); 
} 

使用如下代码启用JSR-250注解的支持

@EnableGlobalMethodSecurity(jsr250Enabled = true) 
public class MethodSecurityConfig { 
// ... 
} 

这些都是基于标准的,并允许应用简单的基于角色的约束,但是没有Spring Security的本地注解的能力。要使用新的基于表达式的语法,你可以使用:

@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig { 
// ... 
} 

和响应的Java代码如下:

public interface BankService { 

@PreAuthorize("isAnonymous()") 
public Account readAccount(Long id); 

@PreAuthorize("isAnonymous()") 
public Account[] findAccounts(); 

@PreAuthorize("hasAuthority('ROLE_TELLER')") 
public Account post(Account account, double amount); 
} 

GlobalMethodSecurityConfiguration

有时候你可能需要执行一些比@ EnableGlobalMethodSecurity注解允许的更复杂的操作。对于这些情况,你可以扩展 GlobalMethodSecurityConfiguration确保@EnableGlobalMethodSecurity注解出现在你的子类。例如:如果你想提供一个定制的MethodSecurityExpressionHander,你可以使用下面的配置:

@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
        // ... create and return custom MethodSecurityExpressionHandler ... 
        return expressionHander; 
    } 
} 

关于可以被重载的方法的更多信息,请参考GlobalMethodSecurityConfiguration的java文档。