已经 SpringSecurity 在几个项目中 实现权限模块,对于数据库,也是思考了不少,从Mysql 到 mongodb 都不是特别满意,

在Mysql中,如果权限相对简单,那么还能接受,如果稍微复杂一点,那么就有点恶心了.

在最近一个项目中,使用mongodb 做多租户的权限,实现起来简单明了了很多,关系也没有那么绕,但是毕竟非关系型数据库,没有级联操作,修改删除,可能会留下一些脏数据,

虽然Spring Data Mongodb 有对象持久化的监听事件,但是依然需要手动编写一些处理过期,以及脏数据的代码.

最近发现有个东西叫做Neo4j,好说了,这个特别关系的数据库,第一个想法,就是很适合做这种关系复杂的权限模块.

这里模拟一个基于多租户的权限设计

1:租户依赖系统权限,根据租户付费套餐不一,拥有不一样的权限,但不可越过系统权限边界(废话)

2:租户可以创建角色(角色不可以越过租户权限的边界)

3:租户创建的用户,可以有多个角色(权限基于租户的权限,多角色叠加)

首先用kubernetes 启动一个neo4j

neo4j.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: neo4j
namespace: k8s-springcloud
spec:
replicas: 1
selector:
matchLabels:
app: neo4j
template:
metadata:
labels:
app: neo4j
spec:
nodeName: k8s-node-0
terminationGracePeriodSeconds: 60
hostNetwork: true
containers:
- name: neo4j
image: 192.168.91.137:5000/neo4j
volumeMounts:
- name: data
mountPath: /data
- name: conf
mountPath: /var/lib/neo4j/conf
volumes:
- name: data
hostPath:
path: /mnt/gv0/k8s-springcloud/neo4j/data
- name: conf
hostPath:
path: /mnt/gv0/k8s-springcloud/neo4j/conf --- apiVersion: v1
kind: Service
metadata:
name: neo4j
namespace: k8s-springcloud
labels:
app: neo4j
spec:
type: NodePort
ports:
- name: api
port: 7687
nodePort: 7687
targetPort: 7687
- name: web
port: 7474
nodePort: 7474
targetPort: 7474

kubectl create -f neo4j.yaml

首先看看系统总权限(假设系统有两个模块:订单(增删改查),库存(增删改查))

代码:

        AclTenantModuleRelation sysModuleRelation = new AclTenantModuleRelation();

        AclModule orderModule = new AclModule();
orderModule.setCode("AUTH_ORDER");
orderModule.setName("订单管理"); AclMethod orderQuery = new AclMethod("AUTH_ORDER_QUERY", "查询订单");
orderQuery.setAclModule(orderModule);
AclMethod orderDelete = new AclMethod("AUTH_ORDER_DELETE", "删除订单");
orderDelete.setAclModule(orderModule);
AclMethod orderEdit = new AclMethod("AUTH_ORDER_EDIT", "编辑订单");
orderEdit.setAclModule(orderModule);
AclMethod orderAdd = new AclMethod("AUTH_ORDER_ADD", "新增订单");
orderAdd.setAclModule(orderModule); orderModule.setAclMethods(new HashSet<>(Arrays.asList(orderAdd, orderDelete, orderEdit, orderQuery))); aclMethodService.saveAll(orderModule.getAclMethods()); aclModuleService.save(orderModule); sysModuleRelation.setTenantId(TenantInfo.SYSTEM_TENANT_ID); AclModule stockModule = new AclModule();
stockModule.setCode("AUTH_STOCK");
stockModule.setName("库存管理"); AclMethod stockQuery = new AclMethod("AUTH_STOCK_QUERY", "查询库存");
stockQuery.setAclModule(stockModule);
AclMethod stockDelete = new AclMethod("AUTH_STOCK_DELETE", "删除库存");
stockDelete.setAclModule(stockModule);
AclMethod stockEdit = new AclMethod("AUTH_STOCK_EDIT", "编辑库存");
stockEdit.setAclModule(stockModule);
AclMethod stockAdd = new AclMethod("AUTH_STOCK_ADD", "新增库存");
stockAdd.setAclModule(stockModule); stockModule.setAclMethods(new HashSet<>(Arrays.asList(stockAdd, stockDelete, stockEdit, stockQuery))); aclMethodService.saveAll(stockModule.getAclMethods()); aclModuleService.save(stockModule); sysModuleRelation.setAclModules(new HashSet<>(Arrays.asList(orderModule,stockModule))); sysModuleRelation.setAclMethods(new HashSet<>(Arrays.asList(orderAdd, orderDelete, orderEdit, orderQuery,stockAdd, stockDelete, stockEdit, stockQuery)));

来设置一个租户,给租户分配一些权限

    /**
* User: laizhenwei
* Date: 2018-03-25 Time: 15:09
*/
@Test
public void initTenantModule(){
AclModule aclModule = aclModuleService.findTop1ByCode("AUTH_STOCK");
TenantInfo tenantInfo = new TenantInfo("租户1");
tenantInfoService.saveAndFlush(tenantInfo);
Iterator<AclMethod> aclMethodIterator = aclModule.getAclMethods().iterator();
AclTenantModuleRelation aclTenantModuleRelation = new AclTenantModuleRelation(tenantInfo.getId(),new HashSet<>(Arrays.asList(aclModule)),new HashSet<>(Arrays.asList(aclMethodIterator.next(),aclMethodIterator.next())));
aclTenantModuleRelationService.save(aclTenantModuleRelation);
}

CQL

match (tenantModule:AclTenantModuleRelation)-[:HAS_OF]->(atMethod:AclMethod) where tenantModule.tenantId = '40288183625d600c01625d6032fa0000' match (atMethod)-[:DEPEND_OF]->(module:AclModule) return atMethod,module

模拟租户创建一个角色

   /**
* User: laizhenwei
* Date: 2018-03-25 Time: 15:09
*/
@Test
public void addRole(){
Optional<AclTenantModuleRelation> aclTenantModuleRelationOptional = aclTenantModuleRelationService.findById(212l);
aclTenantModuleRelationOptional.ifPresent(aclTenantModuleRelation -> {
AclRole aclRole = new AclRole();
aclRole.setTenantId("40288183625d600c01625d6032fa0000");
aclRole.setCode("ROLE_NORMAL");
aclRole.setName("普通用户");
aclRole.setAclTenantModuleRelation(aclTenantModuleRelation);
Iterator<AclModule> aclModuleIterator = aclTenantModuleRelation.getAclModules().iterator();
AclModule aclModule = aclModuleIterator.next();
Iterator<AclMethod> aclMethodIterator = aclTenantModuleRelation.getAclMethods().iterator();
aclRole.setAclModules(new HashSet<>(Arrays.asList(aclModule)));
aclRole.setAclMethods(new HashSet<>(Arrays.asList(aclMethodIterator.next())));
aclRoleService.save(aclRole);
});
}

CQL

match (t:AclTenantModuleRelation)-[:HAS_OF]->(method:AclMethod) match(r:AclRole)-[:HAS_OF]->(rmethod:AclMethod) where r.tenantId='40288183625d600c01625d6032fa0000' and r.code='ROLE_NORMAL' and method=rmethod match(method)-[:DEPEND_OF]->(module:AclModule) return method,module

结果(左),点击展开关系(右)

用户与角色,不再做演示.

想想SpringSecurity 的角色继承的配置格式为  role1>role2>role3 这种方式,用neo4j,是否很好实现动态角色继承?

用图形数据库Neo4j 设计权限模块的更多相关文章

  1. 基于ASP.Net Core开发一套通用后台框架记录-(数据库设计(权限模块))

    写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...

  2. 解析大型.NET ERP系统 权限模块设计与实现

    权限模块是ERP系统的核心模块之一,完善的权限控制机制给系统增色不少.总结我接触过的权限模块,以享读者. 1 权限的简明定义 ERP权限管理用一句简单的话来说就是:谁 能否 做 那些 事. 文句 含义 ...

  3. 权限模块_整体方案说明_设计实体&映射实体_实现初始化权限数据的功能

    权限模块_整体方案说明 要点说明 权限就是控制功能的使用(功能对应着URL). 对功能的控制就是对URL的访问控制. 在我们的程序中,一个功能对应一个或两个URL: 1,例如列表或删除功能,只对应一个 ...

  4. Web应用程序系统的多用户权限控制设计及实现-权限模块【10】

    前五章均是从整体上讲述了Web应用程序的多用户权限控制实现流程,本章讲述Web权限管理系统的权限配置模块.页面模块涉及到的数据表为权限表.权限配置模块是按照用户组和页面,栏目结合组成的.通过配置一个用 ...

  5. 图形数据库Neo4J简介

    最近我在用图形数据库来完成对一个初创项目的支持.在使用过程中觉得这种图形数据库实际上挺有意思的.因此在这里给大家做一个简单的介绍. NoSQL数据库相信大家都听说过.它们常常可以用来处理传统的关系型数 ...

  6. nopcommerce之权限模块

    这篇文章简单介绍一下nopcommerce的权限模块,nopcommerce里面的权限设计相对比较简单,主要针对后台的action和前台的是否显示(比如产品.品牌等),虽然简单但是应付一般的项目应该没 ...

  7. [转]nopcommerce之权限模块

    本文转自:http://www.nopchina.net/category/%E6%9E%B6%E6%9E%84.html 这篇文章简单介绍一下nopcommerce的权限模块,nopcommerce ...

  8. 从零开始编写自己的C#框架(18)——Web层后端权限模块——菜单管理

    从本章开始,主要讲解的是页面中对框架相关功能的调用方法,比如列表页面(又分为有层次感列表和普通列表).编辑页面.多标签页面等,只要熟悉了这些函数的使用方法,那么开发起来就会很便捷了. 1.如图先创建菜 ...

  9. SharePoint 2013 单一页面赋设计权限

    本文介绍SharePoint的使用中,断开单一页面权限,给用户编辑权限以及操作中遇到的问题,希望给相关需要的人一个参考. 1.首先进入页面库,找到我们的页面,进入共享,如下图: 2.在弹出的窗口中选择 ...

随机推荐

  1. iPhone开发中,关于视图跳转的总结(转)

    iPhone开发中,关于视图跳转的总结 iPhone开发中从一个视图跳到另一个视图有三种方法: 1. self.view addSubView:view .self.window addSubView ...

  2. e798. 显示JSlider的标记标签

    This example demonstrates how to display labels (numerical values) at the major ticks (see e797 显示JS ...

  3. mac命令行启动tomcat

    一.修改授权 进入tomcat的bin目录,修改授权 ➜ bin pwd /Users/yp/Documents/workspace/apache-tomcat-7.0.68/bin ➜ bin su ...

  4. C#基础---------------C#正则表达式2

    C#正则表达式语法规则详解 正则表达式基础知识        一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式.   字母文本指的是普通文本如"a ...

  5. (转)最简单的基于FFmpeg的内存读写的例子:内存播放器

    ffmpeg内存播放解码 目录(?)[+] ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章 ...

  6. C# js 在页面能执行,放在单独js文件不能执行

    我们先来看看MVC中生成的 注意:url.Content 生成的路径 Html.ActionLink 与 Url.Action 1.两者者是根据给定的Controller,Action 生成链接, 但 ...

  7. python 程序构架浅析

    定义:通常的 Python 程序的构架是指:将一个程序分割为源代码文件的集合以及将这些部分连接在一起的方法. python的程序构架可表示为: 一个python程序就是一个模块的系统.它有一个顶层文件 ...

  8. TensorFlow-tensorboard可视化

    运行了很多次出现错误,错误原因在于运行tensorboard时,需要退出python编辑

  9. VCL 中的 Windows API 函数(4): AdjustWindowRectEx

    AdjustWindowRectEx 用在了 Forms.DBCtrls 单元. AdjustWindowRectEx 可以根据窗口样式获取的边缘尺寸. 测试: var   R: TRect; beg ...

  10. centos6.8 安装Python2.7后, yum出现“No module named yum”错误

    出现yum错误:No module named yum 解决方法,查看 /usr/bin下python有哪几个版本 ll /usr/bin 我这里是:2.6  和  2.7 (刚安装的) 由于yum命 ...