通用用户权限模型实现

编程

RBAC模型可以分为:RBAC0、RBAC1、RBAC2、RBAC3 四种。其中RBAC0是基础,也是最简单的,相当于底层逻辑,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。

  • RBAC0 :最简单的用户、角色、权限模型 ; 
  • RBAC1: 相对于RBAC0模型,增加了子角色,引入了继承概念,即子角色可以继承父角色的所有权限
  • RBAC2:基于RBAC0模型,增加了对角色的一些限制:角色互斥、基数约束、先决条件角色等。
  • RBAC3: 就是前面几种情况的合集,一般只有在非常复杂的系统中才会用到。

2. 常见权限数据库模型

  • 其中用户与角色是多对多,角色与菜单权限是多对多。
  • 角色与部门是多对多,主要是为了按此角色可以访问哪些部门的数据权限,通过此动态注入相关 sql,到达动态过滤效果。

比较复杂是的数据权限的实现,具体实现过程如下:

 a.定义数据过滤注解

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface DataFilter {

/** 表的别名 */

String tableAlias() default "";

/** true:没有本部门数据权限,也能查询本人数据 */

boolean user() default true;

/** true:拥有子部门数据权限 */

boolean subDept() default false;

/** 部门ID */

String deptId() default "dept_id";

/** 用户ID */

String userId() default "user_id";

}

b.动态SQL拦截注入

@Aspect

@Component

public class DataFilterAspect {

@Autowired

private SysDeptService sysDeptService;

@Autowired

private SysUserRoleService sysUserRoleService;

@Autowired

private SysRoleDeptService sysRoleDeptService;

@Pointcut("@annotation(com.xb.common.annotation.DataFilter)")

public void dataFilterCut() {

}

@Before("dataFilterCut()")

public void dataFilter(JoinPoint point) throws Throwable {

Object params = point.getArgs()[0];

if(params != null && params instanceof Map){

SysUserEntity user = ShiroUtils.getUserEntity();

//如果不是超级管理员,则进行数据过滤

if(user.getUserId() != Constant.SUPER_ADMIN){

Map map = (Map)params;

map.put(Constant.SQL_FILTER, getSQLFilter(user, point));

}

return ;

}

throw new RRException("数据权限接口,只能是Map类型参数,且不能为NULL");

}

/**

* 获取数据过滤的SQL

*/

private String getSQLFilter(SysUserEntity user, JoinPoint point){

MethodSignature signature = (MethodSignature) point.getSignature();

DataFilter dataFilter = signature.getMethod().getAnnotation(DataFilter.class);

//获取表的别名

String tableAlias = dataFilter.tableAlias();

if(StringUtils.isNotBlank(tableAlias)){

tableAlias += ".";

}

//部门ID列表

Set<Long> deptIdList = new HashSet<>();

//用户角色对应的部门ID列表

List<Long> roleIdList = sysUserRoleService.queryRoleIdList(user.getUserId());

if(roleIdList.size() > 0){

List<Long> userDeptIdList = sysRoleDeptService.queryDeptIdList(roleIdList.toArray(new Long[roleIdList.size()]));

deptIdList.addAll(userDeptIdList);

}

//用户子部门ID列表

if(dataFilter.subDept()){

List<Long> subDeptIdList = sysDeptService.getSubDeptIdList(user.getDeptId());

deptIdList.addAll(subDeptIdList);

}

StringBuilder sqlFilter = new StringBuilder();

sqlFilter.append(" (");

if(deptIdList.size() > 0){

sqlFilter.append(tableAlias).append(dataFilter.deptId()).append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");

}

//没有本部门数据权限,也能查询本人数据

if(dataFilter.user()){

if(deptIdList.size() > 0){

sqlFilter.append(" or ");

}

sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getUserId());

}

sqlFilter.append(")");

if(sqlFilter.toString().trim().equals("()")){

return null;

}

return sqlFilter.toString();

}

}

c.service方法使用示例

    @DataFilter(subDept = true, user = false, tableAlias = "t1")
    public List<SysDeptEntity> queryList(Map<String, Object> params){
        return baseMapper.queryList(params);
    }

d.动态加入sql_fliter

	<select id="queryList" resultType="com.xb.modules.sys.entity.SysDeptEntity">

select t1.*,(select t2.name from sys_dept t2 where t2.dept_id=t1.parent_id)parentName from sys_dept t1 where

t1.del_flag = 0

<if test="sql_filter != null">

and ${sql_filter}

</if>

</select>

3. shiro 介绍

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

  • Authentication(认证):用户身份识别,通常被称为用户“登录”
  • Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
  • Session Management(会话管理):特定于用户的会话管理,甚至在非web 或 EJB 应用程序。
  • Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。

Shiro 架构包含三个主要的理念:Subject,SecurityManager和 Realm。下面的图展示了这些组件如何相互作用,我们将在下面依次对其进行描述。

4. shiro 权限控制

Shiro 进行权限控制

四种主要方式 :

a、 在程序中 通过 Subject 编程方式进行权限控制,不常用。

b、 配置 Filter 实现 URL 级别粗粒度权限控制

  • xxx.html* = anon (未登录可以访问)
  • xxx.html* =authc (必须登录才能访问 )
  • xxx.html* = perms[权限] (需要特定权限才能访问)
  • xxx.html* = roles[角色] (需要特定角色才能访问 )

c、 配置代理,基于注解实现细粒度权限控制

  • @RequiresPermissions(权限)  需要特定权限才能访问
  • @RequiresRoles(角色)  需要特定角色才能访问
  • @RequiresAuthentication 需要认证才能访问

d、 在页面中使用 shiro 自定义标签实现 页面显示权限控制

  • <shiro:authenticated> 登录后才能访问
  • <shiro:hasPermission name="abc"> 需要特定权限才能访问
  • <shiro:hasRole name="abc"> 需要特定角色才能访问

 

参考: https://gitee.com/pengchua/webframework_merge/tree/master/web-framework/xb-admin

以上是 通用用户权限模型实现 的全部内容, 来源链接: utcz.com/z/516717.html

回到顶部