Spring保护方法

Spring保护方法

一、使用注解保护方法

1.@Secured

由Spring Security提供,首先需要启用基于注解的方法安全性:

@EnableGlobalMethodSecurity(securedEnabled = true)
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("tang").password("123").roles("USER");
    }
}

如果securedEnabled设置为true,将会创建一个切点,这样Spring Security切面就会包装带有@Secured注解的方法。

@Secured("ROLE_ROOT") //使用String数组作为参数,每个String值是一个权限
    public String addUser() {
        return "add";
    }

如果方法被没有认证的用户或没有所需权限的用户调用,保护这个方法的切面将抛出一个Spring Security异常。

2.JSR-250的@RolesAllowed注解

该注解与@Security注解基本一致,它们的区别在于@RolesAllowed注解是JSR-250定义的标准注解。

如果使用该注解需要将@EnableGlobalMethodSecurity的jsr250Enable属性设置为true。

二、使用表达式实现方法级别的安全性

使用SpEL能够在方法调用上实现更有意思的安全性约束。如果表达式结果为true,那么安全规则通过,否则就会失败。

首先,先要设置prePostEnable属性设置为true。

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("tang").password("123").roles("USER");
    }
}

@PreAuthorize和@PostAuthorize,它们能够基于表达式的计算结果来限制方法的访问。

@PreAuthorize:在方法调用之前执行,如果表达式的计算结果不为true,将会阻止方法

的执行。

@PostAuthorize:直到方法返回才执行,然后决定是否抛出安全异常。

@PreAuthorize("(hasRole('ROLE_ROOT') and #content.text.length() <= 180)")
    public String addUser() {
        return "add";
    }
@PostAuthorize("returnObject.root.username = root.username")
    public String addUser() {
        return "add";
    }

有时需要保护的不是方法调用,而是传入方法的数据和方法返回的数据。

事后对方法的返回值进行过滤   

 @PostAuthorize("returnObject.root.username == root.username")
    //使用表达式计算该方法返回集合的每个成员,将计算结果为false的成员移除掉
    //filterObject对象引用的是这个方法所返回List中的某一个元素
    @PostFilter("hasRole('ROLE_ADMIN') || "
    + "filterObject.admin.username == principal.username")
    public String addUser() {
        return "add";
    }

事先对方法的参数进行过滤 

@PreAuthorize("hasRole({'ROLE_ADMIN', 'ROLE_USER'})")
    @PreFilter("hasRole('ROLE_ADMIN') || " + "targetObject.user.username == user.name")
    public void deleteSth(List<User> userList) {}

应该避免编写复杂的安全表达式,或者在表达式中嵌入太多与安全无关的业务逻辑。而且,表达式

最终只是一个设置给注解的String值,难以测试和调试。

原文地址:https://www.cnblogs.com/Shadowplay/p/10577968.html