Spring Security 中的四种权限控制方式

Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权逻辑。一句话,你想怎么玩都可以!

Spring Security 中四种常见的权限控制方式。

  • 表达式控制 URL 路径权限
  • 表达式控制方法权限
  • 使用过滤注解
  • 动态权限

表达式控制 URL 路径权限

Spring Security 支持在 URL 和方法权限控制时使用 SpEL 表达式,如果表达式返回值为 true 则表示需要对应的权限,否则表示不需要对应的权限。提供表达式的类是 SecurityExpressionRoot:
Spring Security 中的四种权限控制方式_第1张图片

使用案例

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("admin")
            .antMatchers("/user/**").hasAnyRole("admin", "user")
            .anyRequest().authenticated()
            .and()
            ...
}

这里表示访问 /admin/** 格式的路径需要 admin 角色,访问 /user/** 格式的路径需要 admin 或者 user 角色。

表达式控制方法权限

在方法上添加注解控制权限,需要我们首先开启注解的使用,在 Spring Security 配置类上添加如下内容:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ...
    ...
}

这个配置开启了三个注解,分别是:

  • @PreAuthorize:方法执行前进行权限检查
  • @PostAuthorize:方法执行后进行权限检查
  • @Secured:类似于 @PreAuthorize

使用案例

@Service
public class HelloService {
    @PreAuthorize("principal.username.equals('chenfu')")
    public String hello() {
        return "hello";
    }

    @PreAuthorize("hasRole('admin')")
    public String admin() {
        return "admin";
    }

    @PostMapping
    @ApiOperation(value = "等级变更记录分页列表")
    @PreAuthorize("@ato.hasAuthority('msg')")
    public String customer(String msg) {
        return "customer:" + msg;
    }
}

@Slf4j
@Component("ato")
public class AuthorityService {
	/**
	 * 判断接口是否有ato:xxxxx,xxxxx权限
	 *
	 * @param permissions 权限标识
	 * @return {boolean}
	 */
	public boolean hasAuthority(String... permissions) {
		if (ArrayUtil.isEmpty(permissions)) {
			return false;
		}
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return false;
		}
		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
		return authorities.stream()
			.map(GrantedAuthority::getAuthority)
			.filter(StringUtils::hasText)
			.anyMatch(x -> PatternMatchUtils.simpleMatch(permissions, x));
	}
}

  1. 第一个 hello 方法,注解的约束是,只有当前登录用户名为 chenfu 的用户才可以访问该方法。
  2. 第二个 admin 方法,表示访问该方法的用户必须具备 admin 角色。
  3. 第三个 customer 方法,使用自定义类处理逻辑,校验登录用户是否具备接口权限

缺省对象除了 principal ,还有 authentication

使用过滤注解

Spring Security 中还有两个过滤函数 @PreFilter 和 @PostFilter,可以根据给出的条件,自动移除集合中的元素。

@PostFilter("filterObject.lastIndexOf('2')!=-1")
public List<String> getAllUser() {
    List<String> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        users.add("chenfu:" + i);
    }
    return users;
}

@PreFilter(filterTarget = "ages",value = "filterObject%2==0")
public void getAllAge(List<Integer> ages,List<String> users) {
    System.out.println("ages = " + ages);
    System.out.println("users = " + users);
}
  • 在 getAllUser 方法中,对集合进行过滤,只返回后缀为 2 的元素,filterObject 表示要过滤的元素对象。
  • 在 getAllAge 方法中,由于有两个集合,因此使用 filterTarget 指定过滤对象。

动态权限

引用

  1. Spring Security 中的四种权限控制方式

你可能感兴趣的:(Spring,Security,spring,java,后端)