# SAAS-UPMS
**Repository Path**: linux-user/nodecollege-upms
## Basic Information
- **Project Name**: SAAS-UPMS
- **Description**: SAAS通用权限管理系统,包含多租户权限管理系统和运营管理系统,在线IM系统,后端spring cloud,前端vue
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 199
- **Created**: 2020-03-29
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 通用用户权限系统
- 权限和运营后端工程:`/upms`
- 权限前端工程:`/upms-web`
- 运营前端工程:`/upms-operate-web`
- 聊天室后端工程:`/upms-chat`
- 批次管理后端:https://gitee.com/tinyLC/pcgl
- 批次管理前端:https://gitee.com/tinyLC/pcgl-web
- 权限演示地址:http://120.79.216.173:8082 账号/密码: `15739575703`/`123456aA.`
- 运营演示地址:http://120.79.216.173:8082/admin 账号/密码:`admin1/admin2/admin3` / `123456aA.`
### 一、介绍
最近帮我哥写个编号管理系统,顺带写个通用的SAAS用户权限管理系统,方便后期写一些小项目使用。整体使用前后端分离的方式。后端使用sping cloud 用eureka作为注册中心,前端使用vue。用nginx做负载均衡和前端运行环境。
### 二、软件架构
1. 后端框架:spring cloud、mybatis、netty
2. 前端框架:vue、ant-design、echarts
3. 缓存:redis
4. 数据库:
- mysql: (需要修改mapper.xml中模糊查询语句才能正常使用)
- sqlite: (目前正在使用)
### 三、实现的功能:
#### 基础功能
1. 运营人员登陆、注销。
2. 用户注册、登陆、注销。
3. 实时聊天功能。
#### 用户中心(针对用户)
1. 消息:实时聊天功能,好友聊天、群组聊天
2. 通讯录:我的好友、新的好友、我的群组
3. 个人信息修改
4. 我的企业:注册公司、查询我的公司,切换默认登陆公司。
5. 修改密码
6. 切换角色、组织机构
#### 运营后台管理(针对运营人员)
1. 租户管理:租户信息查询,应用、菜单权限开通锁定等。
2. 应用管理:运营、2B、2C应用管理,应用菜单设置,2B预制角色管理。
3. 管理员管理:运营管理人员管理。
4. 运营角色管理:运营角色管理,运营菜单绑定,管理员授权。
5. 用户管理:编辑、删除、重置密码。
6. 配置管理:租户默认开通应用及默认管理员角色设置。
7. 接口管理:微服务接口管理,服务启动自动生成接口数据。
8. 接口访问统计:统计各个接口的访问情况,按小时、按天统计。
#### 系统权限管理(针对租户)
1. 组织机构管理:树状组织机构创建编辑。
2. 成员管理:租户成员查询、邀请、组织机构绑定等。
3. 角色管理:预制与自定义角色管理,角色菜单绑定、组织机构绑定、人员绑定。
4. 菜单管理:拥有菜单查询,后期支持租户自定义菜单。
#### 主要功能介绍
1. 运营后台-租户管理
租户属于2B业务,租户之间数据隔离,可以为不通的租户开通不同的2B应用及相关的菜单权限。
**TODO:** 后期会添加针对租户开通应用及具体菜单的访问量统计功能;添加访问量阈值设定功能;访问量超过阈值,自动进行锁定功能。
**注意:**新注册的租户默认开通系统权限管理的应用权限,但是没有开通改应用下菜单的权限,需要在租户管理-应用信息中单点进行开通。还可以在运营后台-配置管理界面,配置默认开通应用及预制角色。
2. 运营后台-应用管理
应用分为 2B、2C和运营三种类型。
2B针对租户,每个租户各自管理各自的成员,实现了对租户的数据隔离,可以设置预制角色及菜单资源信息。
2C针对该平台用户,可以设置菜单资源。
运营针对运营人员,可以设置菜单资源。
菜单分为分类导航、菜单页面、查询按钮、操作类按钮四类,其中查询和操作类按钮会**绑定接口**信息,用以实现接口级别的权限控制。
预制角色实现了页面及接口访问权限和七级数据权限控制。权限挂接在角色中,通过给组织和人员授权不通的角色,来实现不同的人员权限的控制。
```
0:可以操作该租户的所有数据
1:可以操作所属机构及下级机构所有数据
2:可以操作所属机构及当前机构所有下级机构数据(感觉这级权限有点脱离需求,虽然实现了)
3:可以操作所属机构的数据
4:可以操作当前机构及下级所有机构数据
5:仅能操作当前机构数据
6:仅能操作用户自己的数据
```
3. 预制角色和自定义角色功能
预制角色在运营后台-应用管理进行创建,自定义角色在租户权限管理后台-角色管理界面进行创建。
预制角色的意义及定位:1)每个新建立的租户,其超级管理员必须有管理这个租户所有功能的权限,可以通过授予默认预制角色来快速进行授权,该配置可以在运营后台-配置管理页面进行配置。2)对应人员较少的租户来说,预制角色即可覆盖所有租户成员,方便租户快速掌握使用系统。
自定义角色意义及定位:1)每个租户可以自定义专属于自己的角色,用于满足企业自身的个性化权限控制需求。2)对应人数较多的租户。
角色分为**组织角色**和**组织成员角色**,组织角色给具体的组织机构进行授权,授权后的组织机构下的所有成员都有该角色的权限。组织成员角色需要先对组织机构进行授权,然后需要对该组织机构下的具体成员进行授权,只有该组织机构下的具体成员授权了这个角色,才会拥有这个角色的权限。
组织角色是为了进行批量授权,不用每个成员都单点进行授权。
组织成员角色是为管理人员设置的,例如组织机构的司长、局长、部长、组长之类的,他们的权限需要区别于普通的成员。
4. 运营后台-配置管理
租户默认开通应用及租户管理员默认预制角色管理。
**TODO:** 后期实现默认应用菜单的开通。
5. 运营后台-接口管理
查看该平台所有的接口信息,以应用、controllerName、接口地址进行区分。
**TODO:** 后期实现各个接口的访问量统计信息展示。
6. 运营后台-接口访问统计
现实现:小时-接口访问统计、小时-租户即可访问统计、日-接口访问统计,日-租户访问统计,接口访问量top10,租户访问量top10。
**TODO:** 后期实现IP访问量TOP10、应用内互相调用统计图及对外接口访问统计图。
**注:** 有兴趣的小伙伴可以仔细看下这个页面的ajax请求信息,这六个统计功能全都是一个接口不同的参数实现的。
7. 用户和成员进行区分
用户是平台的用户,成员是租户下的成员,一个用户可以属于多个租户,每个租户下都有各自的成员信息,进行区分的主要目的在于,将租户的成员变成了平台的用户,方便平台进行用户级别的业务需求。
8. 便携的基础集成包,只要是和upms一个注册中心,其他业务微服务引用如下jar包,会自动收集该微服务的所有接口信息及接口访问情况。
```xml
com.nodecollege.cloud
upms-client
0.0.2
```
在进一步,配置该微服务配置参数如下,并且在该微服务controller层添加`@UserLoginAnnotation(checkDataPower = true)`注解,会自动实现接口的访问控制,和数据权限校验。具体的可以参考`pcgl`这个项目。
`application.yml`
```yml
upms:
# 是否校验登陆 默认不校验
loginCheck: true
```
这样做的目的是为了分离业务,各个微服务做各个微服务自己的业务,其他微服务要使用接口权限校验时,直接引包和配参数就行了,不需要自己实现功能。
当然数据级别的权限是需要根据具体业务具体处理的,我这只是提供了一个方便的方式,在调用某个具体的接口后,可以用如下的方式获取具体的数据权限数据和进行校验。
```java
@PostMapping("/getList")
public NCResult getList(@RequestBody QueryVO queryVO) {
ApiDataPower apiDataPower = ThreadUserUtils.getLoginUser().getApiDataPower();
return pcglService.getList(queryVO);
}
```
```java
@Data
public class ApiDataPower {
/**
* 租户id
*/
private Long tenantId;
/**
* 成员id
*/
private Long memberId;
/**
* 能操作的组织机构列表
* 为null,可以操作租户下所有组织机构数据
* 为空, 只能操作当前登陆人的数据,memberId必填
* 不为空,可以操作列表中组织机构的数据
*/
private List orgList;
}
```
9. 接口访问来源校验
访问来源分为两种
- 通过nginx访问的方式,来源固定为nc-nginx
- 通过feign的方式访问,来源为applicationName
添加了@ApiAnnotation注解且checkSource 为 2 的接口会有以下的处理方式
- 需要校验是否登陆
10. 前后端分离,使用了spring cloud (是不是勉强可以称做云服务了`=͟͟͞͞(꒪⌓꒪*))`
11. 实时在线聊天功能
好友聊天、群组聊天、好友添加、群组创建
#### 四、运行
1. 启动eureka
2. 启动redis
3. 修改upms配置文件中数据库信息、redis信息
`\upms\upms-startup\src\main\resources\application.yml`
```
spring:
datasource:
# 数据库文件位置
url: jdbc:sqlite:d:/upms/db/sqlitedb3
redis:
# Redis服务器地址
host: 127.0.0.1
eureka:
client:
service-url:
# eureka地址
defaultZone: http://eurekaIp:eurekaPort/eureka
```
4. 运行upms服务
5. 运行upms-web前端
`\upms-web\`
```
npm run dev
```
6. 运行upms-web-admin前端
`\upms-operate-web\`
```
npm run dev
```
7. 打开浏览器
- 运营地址:http://localhost:8081/admin
- 管理员账号/密码:`admin·`/`123456aA.`
- 系统权限管理地址:http://localhost:8080/
- 用户账号/密码:自己注册去
8. 运行批次管理系统
如上,修改配置文件然后启动即可
- 批次管理系统地址:http://localhost:8082/pcgl/cpj
本地调试需要在http://localhost:8080/ 登陆成功后在源码中设置token信息,不然接口权限校验会失败
`pcgl-web\src\permission.js`
```
router.beforeEach((to, from, next) => {
// 本地测试使用,正式环境需移除 start
// if (!Vue.ls.get(ACCESS_TOKEN)) {
// Vue.ls.set(ACCESS_TOKEN, '078ff8c46f424c1bb4fe805925befcc6')
// Vue.ls.set(USER_INFO, {infoRandom: '42efea56519c46d8a0dc3a9ccfc5d25f'})
// }
// 本地测试使用,正式环境需移除 end
console.log('userInfo', Vue.ls.get(USER_INFO))
if (to.meta.title) {
document.title = to.meta.title
}
if (Vue.ls.get(ACCESS_TOKEN)) {
// 判断当前的token是否存在
next()
} else {
if (to.fullPath.indexOf('/login') >= 0) {
next()
} else {
next({
path: '/login',
query: {redirect: to.fullPath}
})
}
}
})
```
### 五、部署
1. 启动redis
2. eureka、upms后端服务打包后,直接java -jar 启动就行
3. upms-web、upms-web-admin前端打包
```shell
npm run build
```
4. 配置nginx.conf
```
worker_processes 1;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
location / {
# npm-web 打包后的静态文件放在这
root html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /upmsApi/ {
proxy_pass http://localhost:1081/;
}
location /pcglApi/ {
proxy_pass http://localhost:1082/;
}
location /admin {
# npm-web-admin 打包后的静态文件放在这
alias html/adminDist/;
index index.html index.htm;
try_files $uri $uri/ /admin/index.html;
}
location /pcgl {
# pcgl-web 打包后的静态文件放在这
alias html/pcglDist/;
index index.html index.htm;
try_files $uri $uri/ /pcgl/index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
```
5. 启动nginx
- 运营地址:http://ip:8080/admin/
- 系统权限管理地址:http://ip:8080/
6. 结束
#### 六、结束
写的比较简略,后期会把文档补齐。
最后,水平有限,欢迎交流。