在一个系统中,权限的拦截是很常见的事情,通常情况下我们都是基于url进行拦截。那么在spring security中应该怎么配置呢。

大致步骤如下:

1、用户登录成功后我们需要拿到用户所拥有的权限,并保存到当前的认证对象中。

     |- SecurityUserDetailServiceImpl#loadUserByUsername(String) 在根据用户名获取到用户后,一起查询出用户拥有的权限 

2、当用户访问某一个url时,我们需要判断当前访问的url所需要的权限当前认证的用户是否拥有。

    |- 系统加载时需要加载出  所有的资源(url)与之对应的权限

    |- 用户访问url时,如果是有权限判断的url,取出url所需要的权限和用户当前的权限进行一个比对

       > 成功 放行

       > 无权 拒绝

3、修改spring security的配置文件,增加我们自己的权限判断

    那么我们怎么知道我们拥有哪些权限呢?我们可以基于一个简单的rbac的权限模型来进行实现。系统中存在 用户(sys_user),角色(sys_role),资源(sys_resources),用于和角色多对多关系(sys_user_role),角色和资源也是多对多关系(sys_role_resource)。

在资源这张表中记录着url和url所需要的权限。

   基于上一篇 ​​"认识 spring security" ​​​我们来做一个简单的修改,实现url权限的拦截​​。​

、修改SecurityUserDetailServiceImpl这个类,在用户登录成功时,加入用户所拥有的权限
spring security实现简单的url权限拦截_spring security
   注:在上图中可以看到用户拥有 admin、01、0102这三个权限

二、编写一个方法实现系统中的url权限判断

/**
* 系统中的安全资源决策
*
* @描述
* @作者 huan
* @时间 2017年11月4日 - 下午12:32:11
*/
@Slf4j
@Component("securityResourceDecisionHandler")
public class SecurityResourceDecisionHandler {

/**
* 保存的是url以及url所需要的权限
*/
private static final Map<String, List<GrantedAuthority>> URL_AUTHS = new ConcurrentHashMap<>();

static {
URL_AUTHS.put("/xx", Arrays.asList(new SimpleGrantedAuthority("01")));
URL_AUTHS.put("/xx/x", Arrays.asList(new SimpleGrantedAuthority("01")));
URL_AUTHS.put("/yy", Arrays.asList(new SimpleGrantedAuthority("0102")));
URL_AUTHS.put("/zz/**", Arrays.asList(new SimpleGrantedAuthority("010201")));
}
AntPathMatcher pathMatcher = new AntPathMatcher();

/**
* 自定义决策
*
* @param authentication
* 认证对象
* @param request
* 请求的request对象
* @return true:有权限访问 false:无权限访问
*/
public boolean auth(Authentication authentication, HttpServletRequest request) {
String uri = request.getRequestURI().replace(request.getContextPath(), "");
for (Entry<String, List<GrantedAuthority>> entry : URL_AUTHS.entrySet()) {
if (pathMatcher.match(entry.getKey(), uri)) {
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (entry.getValue().contains(grantedAuthority)) {
return true;
}
}
log.warn("当前访问的uri:{},需要的权限是:{},当前用户无此权限.", uri, entry.getValue());
return false;
}
}

// 访问的是没有配置权限的功能,必须要登录用户才可以进行访问
if (authentication.isAuthenticated() && !Objects.equals("anonymousUser", authentication.getPrincipal())) {
return true;
}

// 没有登录,直接返回false
return false;
}
}

   注: 注意一下 /zz/** 这个url所需要的权限是010201,而这个权限当前登录用户是没有的

三、修改spring security的配置文件
spring security实现简单的url权限拦截_用户登录_02
 

四、查看结果(/zz/**这个url需要的权限为010201,而我们只有01,0102,这2个权限,所有就报了无权访问这个。)
spring security实现简单的url权限拦截_spring security_03
 到此,一个基于简单的url拦截的实现就完成了。