diff --git a/README.md b/README.md index 7b98a179..08f37e51 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,12 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 - 关闭签名校验功能 - 整合[easyopen](https://gitee.com/durcframework/easyopen) - Admin管理平台,统一管理微服务配置,管理路由管理,微服务上下线 +- 接入方管理+秘钥管理 +- 接口权限分配 ## 后期规划 -- 接入方管理+秘钥管理 -- 接口权限分配 + - SDK - Spring Cloud Config(Zookeeper) @@ -54,6 +55,8 @@ SOP封装了开放平台大部分功能包括:签名验证、统一异常处 ![admin预览](https://images.gitee.com/uploads/images/2019/0323/142643_6fc1b152_332975.png "admin3.png") +![admin预览](https://images.gitee.com/uploads/images/2019/0401/202931_14cc7248_332975.png "admin7.png") + ## 工程说明 > 运行环境:JDK8,Maven3,Zookeeper diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..883081aa --- /dev/null +++ b/changelog.md @@ -0,0 +1,10 @@ +# changelog + +## 1.1.0 + +- 新增接入方管理 +- 新增接口授权 + +## 1.0.0 + +- 第一次发布 diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 5cbfc891..c41c2a91 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,15 +1,17 @@ -* [首页](/?t=1553593844358) +* [首页](/?t=1554123435599) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1553593844358) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1553593844380) - * [新增接口](files/10020_新增接口.md?t=1553593844380) - * [业务参数校验](files/10030_业务参数校验.md?t=1553593844380) - * [错误处理](files/10040_错误处理.md?t=1553593844380) - * [接口交互详解](files/10050_接口交互详解.md?t=1553593844380) - * [使用SpringCloudGateway](files/10060_使用SpringCloudGateway.md?t=1553593844380) - * [easyopen支持](files/10070_easyopen支持.md?t=1553593844380) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1553593844380) + * [快速体验](files/10010_快速体验.md?t=1554123435601) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1554123435620) + * [新增接口](files/10020_新增接口.md?t=1554123435620) + * [业务参数校验](files/10030_业务参数校验.md?t=1554123435620) + * [错误处理](files/10040_错误处理.md?t=1554123435620) + * [接口交互详解](files/10050_接口交互详解.md?t=1554123435621) + * [使用SpringCloudGateway](files/10060_使用SpringCloudGateway.md?t=1554123435621) + * [easyopen支持](files/10070_easyopen支持.md?t=1554123435621) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1554123435621) + * [ISV管理](files/10085_ISV管理.md?t=1554123435621) + * [路由授权](files/10090_路由授权.md?t=1554123435621) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1553593844380) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1553593844381) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1553593844381) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1554123435621) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1554123435622) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1554123435622) diff --git a/doc/docs/files/10010_快速体验.md b/doc/docs/files/10010_快速体验.md index a9f01d79..d2954f03 100644 --- a/doc/docs/files/10010_快速体验.md +++ b/doc/docs/files/10010_快速体验.md @@ -1,19 +1,21 @@ # 快速体验 -> 运行环境:JDK8,Maven3,Zookeeper +> 运行环境:JDK8,Maven3,Zookeeper,Mysql - 安装并启动zookeeper,[安装教程](http://zookeeper.apache.org/doc/r3.4.13/zookeeperStarted.html) +- 执行Mysql脚本`sop.sql` - IDE打开项目(IDEA下可以打开根pom.xml,然后open as project) - 启动注册中心,sop-registry(运行SopRegistryApplication.java) - 启动微服务:sop-story-web(运行SopStoryApplication.java) -- 启动网关:sop-gateway(运行SopGatewayApplication.java) +- 启动网关:打开sop-gateway下的`application.yml`,修改数据库`username/password`,SopGatewayApplication.java - 找到sop-test,打开测试用例,进行接口调用测试,运行com.gitee.sop.AlipayClientPostTest.testPost() 确保注册中心先启动 ## 使用admin -- 找到`sop-admin/sop-admin-server`工程,运行`com.gitee.sop.adminserver.SopAdminServerApplication.java` +- 找到`sop-admin/sop-admin-server`工程,打开sop-admin-server下的`application-dev.yml`,修改数据库`username/password` +- 运行`com.gitee.sop.adminserver.SopAdminServerApplication.java` - 找到`sop-admin/sop-admin-front/index.html`文件,在IDEA下直接右键--Run'index.html' - 如果没有用到IDEA,则需要把sop-admin-front放到静态服务器中然后访问index.html diff --git a/doc/docs/files/10085_ISV管理.md b/doc/docs/files/10085_ISV管理.md new file mode 100644 index 00000000..991aff16 --- /dev/null +++ b/doc/docs/files/10085_ISV管理.md @@ -0,0 +1,14 @@ +# ISV管理 + +ISV:独立软体开发商(independent software vendor),即接入方或者说接口调用者,在SOP中称为ISV。 + +--- + +在1.1.0版本中新增了ISV管理功能,在sop-admin中ISV管理模块下。功能如下: + +- 基本信息的增查改 +- 设置对应角色 + +界面如下图所示: + +![admin预览](images/10085_1.png "10085_1.png") diff --git a/doc/docs/files/10090_路由授权.md b/doc/docs/files/10090_路由授权.md new file mode 100644 index 00000000..e68c1ec9 --- /dev/null +++ b/doc/docs/files/10090_路由授权.md @@ -0,0 +1,25 @@ +# 路由授权 + +1.1.0版本新增了路由授权功能,采用RBAC权限管理方式实现。 + +- 每个ISV(appKey)对应一个或多个角色 +- 每个角色分配多个路由权限 + +接口跟角色相关联,ISV拥有哪些角色,就具有角色对应的接口访问权限。 + +假设把路由a,b,c分配给了`VIP角色`,那么具有VIP角色的ISV可以访问a,b,c三个路由。 + +默认情况下,接口访问时公开的,ISV都能访问。如果要设置某个接口需要授权,在`@ApiMapping`注解中指定permission=true。 +如:`@ApiMapping(value = "permission.story.get", permission = true)`。这样该接口是需要经过授权给ISV才能访问的。 + +重启服务后,登录admin,服务管理-路由列表界面中,操作操作列会出现一个授权按钮,点击出现授权窗口,勾选对应的角色即可完成授权。 + +- 点击`授权`按钮,进行角色授权 + +![admin预览](images/10090_1.png "10090_1.png") + +- 勾选对应角色,点击保存 + +![admin预览](images/10090_2.png "10090_2.png") + +这里演示的是:具有普通权限的ISV能够访问`permission.story.get`接口,运行`PermissionDemoPostTest`测试用例进行验证 diff --git a/doc/docs/files/90011_原理分析之路由存储.md b/doc/docs/files/90011_原理分析之路由存储.md index cf456fa2..a42c360f 100644 --- a/doc/docs/files/90011_原理分析之路由存储.md +++ b/doc/docs/files/90011_原理分析之路由存储.md @@ -6,7 +6,7 @@ SOP将路由信息存到了zookeeper当中,服务在启动时,将自己的 zookeeper存储路由的结构如下: ```xml -/com.gitee.sop.route- 根节点 +/com.gitee.sop.route 根节点 /serviceId 服务节点,名字为服务名 /route1 路由节点,名字为:name+version,存放路由信息 /route2 diff --git a/doc/docs/files/images/10085_1.png b/doc/docs/files/images/10085_1.png new file mode 100644 index 00000000..fec7db9e Binary files /dev/null and b/doc/docs/files/images/10085_1.png differ diff --git a/doc/docs/files/images/10090_1.png b/doc/docs/files/images/10090_1.png new file mode 100644 index 00000000..27d96a6e Binary files /dev/null and b/doc/docs/files/images/10090_1.png differ diff --git a/doc/docs/files/images/10090_2.png b/doc/docs/files/images/10090_2.png new file mode 100644 index 00000000..ff3c76cf Binary files /dev/null and b/doc/docs/files/images/10090_2.png differ diff --git a/doc/docs/index.html b/doc/docs/index.html index 30b1d454..aaa84ba4 100644 --- a/doc/docs/index.html +++ b/doc/docs/index.html @@ -31,7 +31,10 @@
加载中 ...
+ + + + \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/isv/isvAdd.js b/sop-admin/sop-admin-front/pages/isv/isvAdd.js new file mode 100644 index 00000000..60bade68 --- /dev/null +++ b/sop-admin/sop-admin-front/pages/isv/isvAdd.js @@ -0,0 +1,39 @@ +lib.importJs('../../assets/js/routerole.js') + .use(['element', 'table', 'form'], function () { + var table = layui.table; + var layer = layui.layer; + var form = layui.form; + var $ = layui.jquery; + + var addForm = layui.Form('addForm'); + + $('#createFormDataBtn').click(function () { + ApiUtil.post('isv.form.gen', {}, function (resp) { + addForm.setData(resp.data); + }); + return false; + }); + + form.on('radio(signTypeFilter)', function(data){ + if (data.value == 1) { + $('.sign-type-rsa2').show(); + $('.sign-type-md5').hide(); + } else { + $('.sign-type-rsa2').hide(); + $('.sign-type-md5').show(); + } + }); + + form.on('submit(addFormSubmitFilter)', function (data) { + var param = addForm.getData(); + ApiUtil.post('isv.info.add', param, function (resp) { + layer.alert('添加成功', function () { + location.href = 'isvList.html'; + }) + }) + return false; + }); + + RouteRole.loadAllRole(form, 'roleArea'); + +}); \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/isv/isvList.html b/sop-admin/sop-admin-front/pages/isv/isvList.html new file mode 100644 index 00000000..36d70c60 --- /dev/null +++ b/sop-admin/sop-admin-front/pages/isv/isvList.html @@ -0,0 +1,51 @@ + + + + + SOP Admin + + + + + + + +
+ + 首页 + ISV管理 + ISV列表 + + + +
+
+
+
+ appKey: + + +
+
+ + +
+ +
+ + + + + \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/isv/isvList.js b/sop-admin/sop-admin-front/pages/isv/isvList.js new file mode 100644 index 00000000..60057629 --- /dev/null +++ b/sop-admin/sop-admin-front/pages/isv/isvList.js @@ -0,0 +1,114 @@ +lib.use(['element', 'table', 'form'], function () { + var table = layui.table; + var layer = layui.layer; + var form = layui.form; + var isvTable; + + var STATUS_ENUM = { + '1': '已启用' + ,'2': '已禁用' + } + + // 渲染表格 + var renderTable = function (postData) { + var params = { + data: JSON.stringify(postData || {}) + }; + layer.load(2); + isvTable = table.render({ + elem: '#isvTable' + , toolbar: '#toolbar' + , url: ApiUtil.createUrl('isv.info.page') + // 对分页请求的参数:page、limit重新设定名称 + ,request: { + pageName: 'pageIndex' //页码的参数名称,默认:page + ,limitName: 'pageSize' //每页数据量的参数名,默认:limit + } + , page: true + , where: params + , cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增 + , cols: [[ + {field: 'id', title: 'id', width: 80} + , {field: 'appKey', title: 'appKey', width: 250} + , {field: 'secret', title: 'secret', width: 80, templet: function (row) { + return ''; + }} + , {field: '', title: '公私钥', width: 80, templet: function (row) { + return ''; + }} + , {field: 'roleList', title: '角色', templet: function (row) { + var html = []; + var roleList = row.roleList; + for (var i = 0; i < roleList.length; i++) { + html.push(roleList[i].description); + } + return html.join(', '); + }} + , {field: 'status', title: '状态', width: 80, templet: function (row) { + var display = STATUS_ENUM[row.status + '']; + return display ? display : 'unknown'; + }} + , {field: 'gmtCreate', title: '添加时间', width: 160} + , {field: 'gmtModified', title: '修改时间', width: 160} + , { + fixed: 'right', title: '操作', width: 100, templet: function (row) { + return '修改'; + } + } + ]] + ,parseData: function(res){ //将原始数据解析成 table 组件所规定的数据 + return { + "code": res.code, //解析接口状态 + "msg": res.msg, //解析提示文本 + "count": res.data.total, //解析数据长度 + "data": res.data.list //解析数据列表 + }; + } + ,done: function () { + layer.closeAll('loading'); + } + }); + + //监听单元格事件 + table.on('tool(isvTableFilter)', function(obj) { + if (obj.event === 'edit') { + location.href = 'isvUpdate.html?id=' + obj.data.id; + } + }); + + table.on('toolbar(isvTableFilter)', function(obj) { + if (obj.event === 'add') { + location.href = 'isvAdd.html'; + } + }); + }; + + renderTable(); + + form.on('submit(searchFilter)', function(data){ + var param = data.field; + renderTable(param) + return false; + }); + + + window.View = { + secret: function (secret) { + layer.alert(secret); + } + ,pubPriKey: function (pubKey, priKey) { + var content = '
公钥:
' + + '私钥:
'; + layer.open({ + type: 1, + area: ['600px', '400px'], + fix: false, //不固定 + shadeClose: true, + shade:0.4, + title: '公私钥', + content: content + }); + } + } + +}); \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/isv/isvUpdate.html b/sop-admin/sop-admin-front/pages/isv/isvUpdate.html new file mode 100644 index 00000000..87232a78 --- /dev/null +++ b/sop-admin/sop-admin-front/pages/isv/isvUpdate.html @@ -0,0 +1,97 @@ + + + + + SOP Admin + + + + + + + + +
+ + 首页 + ISV管理 + ISV列表 + 修改ISV + + + +
+
+
+ 修改ISV +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+ +
+ + +
+
+
+
+ + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/isv/isvUpdate.js b/sop-admin/sop-admin-front/pages/isv/isvUpdate.js new file mode 100644 index 00000000..9936b641 --- /dev/null +++ b/sop-admin/sop-admin-front/pages/isv/isvUpdate.js @@ -0,0 +1,62 @@ +lib.importJs('../../assets/js/routerole.js') + .use(['element', 'table', 'form'], function () { + var table = layui.table; + var layer = layui.layer; + var form = layui.form; + var $ = layui.jquery; + + var updateForm = layui.Form('updateForm'); + + $('#createFormDataBtn').click(function () { + ApiUtil.post('isv.form.gen', {}, function (resp) { + var data = resp.data; + var appKey = updateForm.getData('appKey'); + data.appKey = appKey; + updateForm.setData(data); + + }); + return false; + }); + + form.on('radio(signTypeFilter)', function(data){ + if (data.value == 1) { + $('.sign-type-rsa2').show(); + $('.sign-type-md5').hide(); + } else { + $('.sign-type-rsa2').hide(); + $('.sign-type-md5').show(); + } + }); + + form.on('submit(updateFormSubmitFilter)', function (data) { + var param = updateForm.getData(); + ApiUtil.post('isv.info.update', param, function (resp) { + layer.alert('修改成功', function () { + location.href = 'isvList.html'; + }) + }) + return false; + }); + + RouteRole.loadAllRole(form, 'roleArea', function () { + loadFormData(); + }) + + function loadFormData() { + var id = ApiUtil.getParam('id'); + if (!id) { + alert('id错误'); + return; + } + ApiUtil.post('isv.info.get', {id: id}, function (resp) { + var isvInfo = resp.data; + var roleList = isvInfo.roleList; + var roleCode = []; + for (var i = 0; i < roleList.length; i++) { + roleCode.push(roleList[i].roleCode); + } + isvInfo.roleCode = roleCode; + updateForm.setData(isvInfo); + }); + } +}); \ No newline at end of file diff --git a/sop-admin/sop-admin-front/pages/service/routeManager.html b/sop-admin/sop-admin-front/pages/service/routeManager.html index e826bb6d..3263de68 100644 --- a/sop-admin/sop-admin-front/pages/service/routeManager.html +++ b/sop-admin/sop-admin-front/pages/service/routeManager.html @@ -22,9 +22,6 @@
-
- -
    @@ -57,14 +54,13 @@
    -