mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
网关可校验token
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# changelog
|
# changelog
|
||||||
|
|
||||||
|
## 2.5.0
|
||||||
|
|
||||||
|
- 网关可校验token,见`com.gitee.sop.storyweb.controller.TokenController`(需要执行`sop-2.5.0.sql`升级文件)
|
||||||
|
|
||||||
## 2.4.1
|
## 2.4.1
|
||||||
|
|
||||||
- 优化restful接口调用(如果正在使用此功能,必看 [doc](https://durcframework.gitee.io/sop/#/files/10100_%E6%8F%90%E4%BE%9Brestful%E6%8E%A5%E5%8F%A3?t=1571107529449))
|
- 优化restful接口调用(如果正在使用此功能,必看 [doc](https://durcframework.gitee.io/sop/#/files/10100_%E6%8F%90%E4%BE%9Brestful%E6%8E%A5%E5%8F%A3?t=1571107529449))
|
||||||
|
@@ -1,34 +1,35 @@
|
|||||||
* [首页](/?t=1571107529420)
|
* [首页](/?t=1572076365237)
|
||||||
* 开发文档
|
* 开发文档
|
||||||
* [快速体验](files/10010_快速体验.md?t=1571107529423)
|
* [快速体验](files/10010_快速体验.md?t=1572076365239)
|
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1571107529447)
|
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1572076365257)
|
||||||
* [新增接口](files/10020_新增接口.md?t=1571107529447)
|
* [新增接口](files/10020_新增接口.md?t=1572076365257)
|
||||||
* [开发流程](files/10021_开发流程.md?t=1571107529447)
|
* [开发流程](files/10021_开发流程.md?t=1572076365257)
|
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1571107529447)
|
* [业务参数校验](files/10030_业务参数校验.md?t=1572076365258)
|
||||||
* [错误处理](files/10040_错误处理.md?t=1571107529447)
|
* [错误处理](files/10040_错误处理.md?t=1572076365258)
|
||||||
* [编写文档](files/10041_编写文档.md?t=1571107529447)
|
* [编写文档](files/10041_编写文档.md?t=1572076365258)
|
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1571107529448)
|
* [接口交互详解](files/10050_接口交互详解.md?t=1572076365258)
|
||||||
* [easyopen支持](files/10070_easyopen支持.md?t=1571107529448)
|
* [easyopen支持](files/10070_easyopen支持.md?t=1572076365258)
|
||||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1571107529448)
|
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1572076365258)
|
||||||
* [ISV管理](files/10085_ISV管理.md?t=1571107529448)
|
* [ISV管理](files/10085_ISV管理.md?t=1572076365258)
|
||||||
* [自定义返回结果](files/10087_自定义返回结果.md?t=1571107529448)
|
* [自定义返回结果](files/10087_自定义返回结果.md?t=1572076365259)
|
||||||
* [自定义过滤器](files/10088_自定义过滤器.md?t=1571107529448)
|
* [自定义过滤器](files/10088_自定义过滤器.md?t=1572076365259)
|
||||||
* [路由授权](files/10090_路由授权.md?t=1571107529448)
|
* [自定义校验token](files/10089_自定义校验token.md?t=1572076365259)
|
||||||
* [接口限流](files/10092_接口限流.md?t=1571107529448)
|
* [路由授权](files/10090_路由授权.md?t=1572076365259)
|
||||||
* [监控日志](files/10093_监控日志.md?t=1571107529448)
|
* [接口限流](files/10092_接口限流.md?t=1572076365259)
|
||||||
* [SDK开发](files/10095_SDK开发.md?t=1571107529449)
|
* [监控日志](files/10093_监控日志.md?t=1572076365259)
|
||||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1571107529449)
|
* [SDK开发](files/10095_SDK开发.md?t=1572076365259)
|
||||||
* [应用授权](files/10097_应用授权.md?t=1571107529449)
|
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1572076365260)
|
||||||
* [提供restful接口](files/10100_提供restful接口.md?t=1571107529449)
|
* [应用授权](files/10097_应用授权.md?t=1572076365260)
|
||||||
* [文件上传](files/10104_文件上传.md?t=1571107529449)
|
* [提供restful接口](files/10100_提供restful接口.md?t=1572076365260)
|
||||||
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1571107529449)
|
* [文件上传](files/10104_文件上传.md?t=1572076365260)
|
||||||
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1571107529449)
|
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1572076365260)
|
||||||
* [动态修改请求参数](files/10111_动态修改请求参数.md?t=1571107529450)
|
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1572076365261)
|
||||||
* [使用eureka](files/10112_使用eureka.md?t=1571107529450)
|
* [动态修改请求参数](files/10111_动态修改请求参数.md?t=1572076365261)
|
||||||
* [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1571107529450)
|
* [使用eureka](files/10112_使用eureka.md?t=1572076365261)
|
||||||
|
* [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1572076365261)
|
||||||
* 原理分析
|
* 原理分析
|
||||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1571107529450)
|
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1572076365261)
|
||||||
* [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1571107529450)
|
* [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1572076365261)
|
||||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1571107529450)
|
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1572076365261)
|
||||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1571107529450)
|
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1572076365262)
|
||||||
* [常见问题](files/90100_常见问题.md?t=1571107529450)
|
* [常见问题](files/90100_常见问题.md?t=1572076365262)
|
||||||
|
54
doc/docs/files/10089_自定义校验token.md
Normal file
54
doc/docs/files/10089_自定义校验token.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# 自定义校验token(2.5.0)
|
||||||
|
|
||||||
|
从2.5.0开始在`@ApiMapping`注解中新增了一个属性`needToken`,用来告诉网关是否校验token
|
||||||
|
|
||||||
|
```java
|
||||||
|
/**
|
||||||
|
* 是否需要appAuthToken,设置为true,网关端会校验token是否存在
|
||||||
|
*/
|
||||||
|
boolean needToken() default false;
|
||||||
|
```
|
||||||
|
|
||||||
|
使用方式:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@ApiMapping(value = "story.token.get", needToken = true/* 设置true,网关会校验token是否存在 */)
|
||||||
|
public StoryResult token(StoryParam story) {
|
||||||
|
OpenContext openContext = ServiceContext.getCurrentContext().getOpenContext();
|
||||||
|
String appAuthToken = openContext.getAppAuthToken();
|
||||||
|
StoryResult result = new StoryResult();
|
||||||
|
result.setName("appAuthToken:" + appAuthToken);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
指定了needToken=true后,网关会判断客户端是否传了`app_auth_token`参数,没有传则返回错误信息。
|
||||||
|
|
||||||
|
网关默认简单校验参数值是否存在,如果要校验有效性,需要自己实现。
|
||||||
|
|
||||||
|
自己实现步骤:
|
||||||
|
|
||||||
|
- 在ZuulConfig类中重写`doAfter`方法
|
||||||
|
- 设置`ApiConfig中的tokenValidator属性`
|
||||||
|
|
||||||
|
`TokenValidator`是一个函数式接口,可以直接使用Lambda表达式,示例代码如下:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class ZuulConfig extends AlipayZuulConfiguration {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doAfter() {
|
||||||
|
ApiConfig.getInstance().setTokenValidator(apiParam -> {
|
||||||
|
// 获取客户端传递过来的token
|
||||||
|
String token = apiParam.fetchAccessToken();
|
||||||
|
if (StringUtils.isBlank(token)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO: 校验token有效性,可以从redis中读取
|
||||||
|
|
||||||
|
// 返回true表示这个token真实、有效
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
1
sop-2.5.0.sql
Normal file
1
sop-2.5.0.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `sop`.`config_service_route` ADD COLUMN `need_token` TINYINT NOT NULL DEFAULT 0 COMMENT '是否需要token' AFTER `permission`;
|
@@ -26,4 +26,8 @@ public class RouteSearchParam extends PageParam {
|
|||||||
@ApiDocField(description = "是否授权接口,1:是")
|
@ApiDocField(description = "是否授权接口,1:是")
|
||||||
@Condition(ignoreValue = "0")
|
@Condition(ignoreValue = "0")
|
||||||
private Integer permission;
|
private Integer permission;
|
||||||
|
|
||||||
|
@ApiDocField(description = "是否需要token接口,1:是")
|
||||||
|
@Condition(ignoreValue = "0")
|
||||||
|
private Integer needToken;
|
||||||
}
|
}
|
||||||
|
@@ -49,6 +49,9 @@ public class RouteVO {
|
|||||||
/** 是否合并结果, 数据库字段:merge_result */
|
/** 是否合并结果, 数据库字段:merge_result */
|
||||||
private Byte mergeResult;
|
private Byte mergeResult;
|
||||||
|
|
||||||
|
/** 是否需要token, 数据库字段:need_token */
|
||||||
|
private Byte needToken;
|
||||||
|
|
||||||
/** 是否需要授权才能访问, 数据库字段:permission */
|
/** 是否需要授权才能访问, 数据库字段:permission */
|
||||||
private Byte permission;
|
private Byte permission;
|
||||||
|
|
||||||
|
@@ -61,6 +61,9 @@ public class ConfigServiceRoute {
|
|||||||
/** 是否需要授权才能访问, 数据库字段:permission */
|
/** 是否需要授权才能访问, 数据库字段:permission */
|
||||||
private Byte permission;
|
private Byte permission;
|
||||||
|
|
||||||
|
/** 是否需要token, 数据库字段:need_token */
|
||||||
|
private Byte needToken;
|
||||||
|
|
||||||
/** 数据库字段:gmt_create */
|
/** 数据库字段:gmt_create */
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.c6dfb7ee.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],d=0,l=[];d<a.length;d++)c=a[d],u[c]&&l.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(l.length)l.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"88458f58","chunk-25908fca":"05d6b15b","chunk-2c1f2e8f":"f092c0a0","chunk-2d2085ef":"91d75f3c","chunk-2d221c34":"20057287","chunk-4de1c2b6":"e74e3d03","chunk-6f78c9fe":"3ac83b41","chunk-73b2dcec":"05b5ee28","chunk-9b31c83a":"e60adb43","chunk-9f479afe":"0d0ed757","chunk-c3ce42fe":"9517b588"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-0faf9ba2":1,"chunk-25908fca":1,"chunk-2c1f2e8f":1,"chunk-4de1c2b6":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-c3ce42fe":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"ed1510dd","chunk-25908fca":"89ab33e8","chunk-2c1f2e8f":"0314067f","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-4de1c2b6":"a37cd815","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-c3ce42fe":"6b789903"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],d=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(d===r||d===u))return n()}var l=document.getElementsByTagName("style");for(a=0;a<l.length;a++){i=l[a],d=i.getAttribute("data-href");if(d===r||d===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,d=document.createElement("script");d.charset="utf-8",d.timeout=120,f.nc&&d.setAttribute("nonce",f.nc),d.src=a(e),i=function(n){d.onerror=d.onload=null,clearTimeout(l);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var l=setTimeout(function(){i({type:"timeout",target:d})},12e4);d.onerror=d.onload=i,document.head.appendChild(d)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],d=i.push.bind(i);i.push=n,i=i.slice();for(var l=0;l<i.length;l++)n(i[l]);var h=d;t()})([]);</script><script src=static/js/chunk-elementUI.298ac98c.js></script><script src=static/js/chunk-libs.75deb05f.js></script><script src=static/js/app.f05d6d01.js></script></body></html>
|
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.c6dfb7ee.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],d=0,l=[];d<a.length;d++)c=a[d],u[c]&&l.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(l.length)l.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"88458f58","chunk-25908fca":"05d6b15b","chunk-2c1f2e8f":"f092c0a0","chunk-2d2085ef":"91d75f3c","chunk-2d221c34":"20057287","chunk-4de1c2b6":"e74e3d03","chunk-6f78c9fe":"3ac83b41","chunk-73b2dcec":"05b5ee28","chunk-9b31c83a":"52bc6b2c","chunk-9f479afe":"0d0ed757","chunk-c3ce42fe":"9517b588"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-0faf9ba2":1,"chunk-25908fca":1,"chunk-2c1f2e8f":1,"chunk-4de1c2b6":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-c3ce42fe":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"ed1510dd","chunk-25908fca":"89ab33e8","chunk-2c1f2e8f":"0314067f","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-4de1c2b6":"a37cd815","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-c3ce42fe":"6b789903"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],d=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(d===r||d===u))return n()}var l=document.getElementsByTagName("style");for(a=0;a<l.length;a++){i=l[a],d=i.getAttribute("data-href");if(d===r||d===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,d=document.createElement("script");d.charset="utf-8",d.timeout=120,f.nc&&d.setAttribute("nonce",f.nc),d.src=a(e),i=function(n){d.onerror=d.onload=null,clearTimeout(l);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var l=setTimeout(function(){i({type:"timeout",target:d})},12e4);d.onerror=d.onload=i,document.head.appendChild(d)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],d=i.push.bind(i);i.push=n,i=i.slice();for(var l=0;l<i.length;l++)n(i[l]);var h=d;t()})([]);</script><script src=static/js/chunk-elementUI.298ac98c.js></script><script src=static/js/chunk-libs.75deb05f.js></script><script src=static/js/app.f05d6d01.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -66,6 +66,9 @@
|
|||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-checkbox v-model="searchFormData.permission">授权接口</el-checkbox>
|
<el-checkbox v-model="searchFormData.permission">授权接口</el-checkbox>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-checkbox v-model="searchFormData.needToken">需要token</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" @click="onSearchTable">查询</el-button>
|
<el-button type="primary" icon="el-icon-search" @click="onSearchTable">查询</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -123,6 +126,16 @@
|
|||||||
<span v-if="scope.row.mergeResult === 0" style="color:#E6A23C">否</span>
|
<span v-if="scope.row.mergeResult === 0" style="color:#E6A23C">否</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="needToken"
|
||||||
|
label="需要token"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="scope.row.needToken === 1" style="font-weight: bold;color: #303133;">是</span>
|
||||||
|
<span v-if="scope.row.needToken === 0">否</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="status"
|
prop="status"
|
||||||
label="状态"
|
label="状态"
|
||||||
@@ -182,6 +195,9 @@
|
|||||||
<el-form-item label="统一格式输出">
|
<el-form-item label="统一格式输出">
|
||||||
{{ routeDialogFormData.mergeResult === 1 ? '是' : '否' }}
|
{{ routeDialogFormData.mergeResult === 1 ? '是' : '否' }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="需要token">
|
||||||
|
{{ routeDialogFormData.needToken === 1 ? '是' : '否' }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<el-radio-group v-model="routeDialogFormData.status">
|
<el-radio-group v-model="routeDialogFormData.status">
|
||||||
<el-radio :label="1" name="status">启用</el-radio>
|
<el-radio :label="1" name="status">启用</el-radio>
|
||||||
@@ -269,6 +285,7 @@ export default {
|
|||||||
id: '',
|
id: '',
|
||||||
serviceId: '',
|
serviceId: '',
|
||||||
permission: 0,
|
permission: 0,
|
||||||
|
needToken: 0,
|
||||||
pageIndex: 1,
|
pageIndex: 1,
|
||||||
pageSize: 10
|
pageSize: 10
|
||||||
},
|
},
|
||||||
|
@@ -32,12 +32,14 @@ import com.gitee.sop.gatewaycommon.validate.ApiSigner;
|
|||||||
import com.gitee.sop.gatewaycommon.validate.ApiValidator;
|
import com.gitee.sop.gatewaycommon.validate.ApiValidator;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Encrypter;
|
import com.gitee.sop.gatewaycommon.validate.Encrypter;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Signer;
|
import com.gitee.sop.gatewaycommon.validate.Signer;
|
||||||
|
import com.gitee.sop.gatewaycommon.validate.TokenValidator;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
|
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder;
|
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
|
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -152,6 +154,11 @@ public class ApiConfig {
|
|||||||
|
|
||||||
private ParameterFormatter parameterFormatter;
|
private ParameterFormatter parameterFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验token
|
||||||
|
*/
|
||||||
|
private TokenValidator tokenValidator = apiParam -> apiParam != null && StringUtils.isNotBlank(apiParam.fetchAccessToken());
|
||||||
|
|
||||||
// -------- fields ---------
|
// -------- fields ---------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,46 +0,0 @@
|
|||||||
package com.gitee.sop.gatewaycommon.bean;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author tanghc
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class BaseRouteDefinition {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 路由的Id
|
|
||||||
*/
|
|
||||||
private String id;
|
|
||||||
/**
|
|
||||||
* 路由规则转发的目标uri
|
|
||||||
*/
|
|
||||||
private String uri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* uri后面跟的path
|
|
||||||
*/
|
|
||||||
private String path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 路由执行的顺序
|
|
||||||
*/
|
|
||||||
private int order = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否忽略验证,业务参数验证除外
|
|
||||||
*/
|
|
||||||
private int ignoreValidate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否合并结果
|
|
||||||
*/
|
|
||||||
private int mergeResult;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 接口是否需要授权才能访问
|
|
||||||
*/
|
|
||||||
private int permission;
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
package com.gitee.sop.gatewaycommon.bean;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author tanghc
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class BaseServiceRouteInfo<T extends BaseRouteDefinition> {
|
|
||||||
private String serviceId;
|
|
||||||
private List<T> routeDefinitionList = Collections.emptyList();
|
|
||||||
|
|
||||||
public String fetchServiceIdLowerCase() {
|
|
||||||
return this.serviceId.toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -70,4 +70,9 @@ public class RouteDefinition {
|
|||||||
* 是否需要授权才能访问
|
* 是否需要授权才能访问
|
||||||
*/
|
*/
|
||||||
private int permission;
|
private int permission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要token
|
||||||
|
*/
|
||||||
|
private int needToken;
|
||||||
}
|
}
|
@@ -16,6 +16,8 @@ import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
|
|||||||
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
|
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
@@ -25,13 +27,19 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.core.io.buffer.DataBuffer;
|
||||||
|
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicate;
|
||||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -41,6 +49,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class BaseGatewayConfiguration extends AbstractConfiguration {
|
public class BaseGatewayConfiguration extends AbstractConfiguration {
|
||||||
|
|
||||||
public BaseGatewayConfiguration() {
|
public BaseGatewayConfiguration() {
|
||||||
@@ -152,12 +161,20 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "sop.restful.enable", havingValue = "true")
|
@ConditionalOnProperty(value = "sop.restful.enable", havingValue = "true")
|
||||||
RouterFunction<ServerResponse> routerFunction() {
|
RouterFunction<ServerResponse> routerFunction() {
|
||||||
return RouterFunctions.route(RequestPredicates.GET(restPath + "/**"), (serverRequest) -> {
|
RequestPredicate requestPredicate = RequestPredicates.all()
|
||||||
String url = serverRequest.path();
|
.and(RequestPredicates.path(restPath + "/**"));
|
||||||
int index = url.indexOf(restPath);
|
return RouterFunctions.route(requestPredicate, (serverRequest) -> {
|
||||||
|
String path = serverRequest.path();
|
||||||
|
int index = path.indexOf(restPath);
|
||||||
// 取/rest的后面部分
|
// 取/rest的后面部分
|
||||||
String path = url.substring(index + restPath.length());
|
String servletPath = path.substring(index + restPath.length());
|
||||||
String query = ParamNames.API_NAME + "=" + path + "&" + ParamNames.VERSION_NAME + "=";
|
String query = serverRequest.uri().getQuery();
|
||||||
|
String appendQuery = ParamNames.API_NAME + "=" + servletPath + "&" + ParamNames.VERSION_NAME + "=";
|
||||||
|
if (StringUtils.isBlank(query)) {
|
||||||
|
query = appendQuery;
|
||||||
|
} else {
|
||||||
|
query += '&' + appendQuery;
|
||||||
|
}
|
||||||
return ServerResponse
|
return ServerResponse
|
||||||
.temporaryRedirect(URI.create("/?" + query))
|
.temporaryRedirect(URI.create("/?" + query))
|
||||||
.build();
|
.build();
|
||||||
|
@@ -21,7 +21,12 @@ public enum EnvironmentKeys {
|
|||||||
/**
|
/**
|
||||||
* sop.restful.enable=true,开启传统web开发模式
|
* sop.restful.enable=true,开启传统web开发模式
|
||||||
*/
|
*/
|
||||||
SOP_RESTFUL_ENABLE("sop.restful.enable");
|
SOP_RESTFUL_ENABLE("sop.restful.enable"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sop.restful.path=/xx ,指定请求前缀,默认/rest
|
||||||
|
*/
|
||||||
|
SOP_RESTFUL_PATH("sop.restful.path", "/rest");
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
private String defaultValue;
|
private String defaultValue;
|
||||||
|
@@ -83,6 +83,7 @@ public class ApiValidator implements Validator {
|
|||||||
checkFormat(param);
|
checkFormat(param);
|
||||||
checkUploadFile(param);
|
checkUploadFile(param);
|
||||||
checkPermission(param);
|
checkPermission(param);
|
||||||
|
checkToken(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,7 +239,7 @@ public class ApiValidator implements Validator {
|
|||||||
/**
|
/**
|
||||||
* 校验访问权限
|
* 校验访问权限
|
||||||
*
|
*
|
||||||
* @param apiParam
|
* @param apiParam 参数
|
||||||
*/
|
*/
|
||||||
protected void checkPermission(ApiParam apiParam) {
|
protected void checkPermission(ApiParam apiParam) {
|
||||||
String routeId = apiParam.fetchNameVersion();
|
String routeId = apiParam.fetchNameVersion();
|
||||||
@@ -254,4 +255,23 @@ public class ApiValidator implements Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验token
|
||||||
|
*
|
||||||
|
* @param apiParam 参数
|
||||||
|
*/
|
||||||
|
protected void checkToken(ApiParam apiParam) {
|
||||||
|
String routeId = apiParam.fetchNameVersion();
|
||||||
|
TargetRoute targetRoute = RouteRepositoryContext.getRouteRepository().get(routeId);
|
||||||
|
RouteDefinition routeDefinition = targetRoute.getRouteDefinition();
|
||||||
|
boolean needToken = BooleanUtils.toBoolean(routeDefinition.getNeedToken());
|
||||||
|
if (needToken) {
|
||||||
|
TokenValidator tokenValidator = ApiConfig.getInstance().getTokenValidator();
|
||||||
|
boolean rightToken = tokenValidator.validateToken(apiParam);
|
||||||
|
if (!rightToken) {
|
||||||
|
throw ErrorEnum.AOP_INVALID_APP_AUTH_TOKEN.getErrorMeta().getException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
package com.gitee.sop.gatewaycommon.validate;
|
||||||
|
|
||||||
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface TokenValidator {
|
||||||
|
boolean validateToken(ApiParam apiParam);
|
||||||
|
}
|
@@ -35,4 +35,9 @@ public @interface ApiAbility {
|
|||||||
* 指定接口是否需要授权才能访问,可在admin中进行修改
|
* 指定接口是否需要授权才能访问,可在admin中进行修改
|
||||||
*/
|
*/
|
||||||
boolean permission() default false;
|
boolean permission() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要appAuthToken,设置为true,网关端会校验token是否存在
|
||||||
|
*/
|
||||||
|
boolean needToken() default false;
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@ public @interface ApiMapping {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 版本号,默认版本号是""<br>
|
* 版本号,默认版本号是""<br>
|
||||||
* 改默认版本号:<code>ServiceContext.getSopServerConfig().setDefaultVersion("1.0");</code>
|
* 改默认版本号:<code>ServiceConfig.getInstance().setDefaultVersion("1.0");</code>
|
||||||
*/
|
*/
|
||||||
String version() default "";
|
String version() default "";
|
||||||
|
|
||||||
@@ -44,6 +44,11 @@ public @interface ApiMapping {
|
|||||||
*/
|
*/
|
||||||
boolean permission() default false;
|
boolean permission() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要appAuthToken,设置为true,网关端会校验token是否存在
|
||||||
|
*/
|
||||||
|
boolean needToken() default false;
|
||||||
|
|
||||||
// ------------ 自定义属性 end ------------
|
// ------------ 自定义属性 end ------------
|
||||||
|
|
||||||
|
|
||||||
|
@@ -80,12 +80,23 @@ public interface OpenContext<T> extends OpenBeanFactory {
|
|||||||
*/
|
*/
|
||||||
Date getTimestamp();
|
Date getTimestamp();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回token,即access_token.
|
||||||
|
*
|
||||||
|
* @deprecated 废弃,使用getAppAuthToken()
|
||||||
|
* @return 返回token
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
String appAuthToken();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回token,即access_token
|
* 返回token,即access_token
|
||||||
*
|
*
|
||||||
* @return 返回token
|
* @return 返回token
|
||||||
*/
|
*/
|
||||||
String appAuthToken();
|
default String getAppAuthToken() {
|
||||||
|
return appAuthToken();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回回调地址
|
* 返回回调地址
|
||||||
|
@@ -28,6 +28,8 @@ public class ServiceApiInfo {
|
|||||||
private int mergeResult;
|
private int mergeResult;
|
||||||
/** 是否需要授权才能访问 */
|
/** 是否需要授权才能访问 */
|
||||||
private int permission;
|
private int permission;
|
||||||
|
/** 是否需要token */
|
||||||
|
private int needToken;
|
||||||
/** 是否是原始Mapping */
|
/** 是否是原始Mapping */
|
||||||
private boolean originalMapping;
|
private boolean originalMapping;
|
||||||
|
|
||||||
|
@@ -87,6 +87,7 @@ public class ApiMetaBuilder {
|
|||||||
apiMeta.setIgnoreValidate(BooleanUtils.toInteger(apiMappingInfo.isIgnoreValidate()));
|
apiMeta.setIgnoreValidate(BooleanUtils.toInteger(apiMappingInfo.isIgnoreValidate()));
|
||||||
apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
|
apiMeta.setMergeResult(BooleanUtils.toInteger(apiMappingInfo.isMergeResult()));
|
||||||
apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission()));
|
apiMeta.setPermission(BooleanUtils.toInteger(apiMappingInfo.isPermission()));
|
||||||
|
apiMeta.setNeedToken(BooleanUtils.toInteger(apiMappingInfo.isNeedToken()));
|
||||||
return apiMeta;
|
return apiMeta;
|
||||||
} else {
|
} else {
|
||||||
if (!ServiceContext.getCurrentContext().getBoolean(ServiceContext.RESTFUL_KEY, false)) {
|
if (!ServiceContext.getCurrentContext().getBoolean(ServiceContext.RESTFUL_KEY, false)) {
|
||||||
|
@@ -50,8 +50,8 @@ public class ServiceRouteInfoBuilder {
|
|||||||
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
|
List<ServiceApiInfo.ApiMeta> apis = serviceApiInfo.getApis();
|
||||||
List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size());
|
List<RouteDefinition> routeDefinitionList = new ArrayList<>(apis.size());
|
||||||
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
|
for (ServiceApiInfo.ApiMeta apiMeta : apis) {
|
||||||
RouteDefinition gatewayRouteDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
|
RouteDefinition routeDefinition = this.buildGatewayRouteDefinition(serviceApiInfo, apiMeta);
|
||||||
routeDefinitionList.add(gatewayRouteDefinition);
|
routeDefinitionList.add(routeDefinition);
|
||||||
}
|
}
|
||||||
ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo();
|
ServiceRouteInfo serviceRouteInfo = new ServiceRouteInfo();
|
||||||
serviceRouteInfo.setServiceId(serviceApiInfo.getServiceId());
|
serviceRouteInfo.setServiceId(serviceApiInfo.getServiceId());
|
||||||
|
@@ -35,9 +35,10 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
String name = null;
|
String name = null;
|
||||||
String version;
|
String version;
|
||||||
boolean ignoreValidate = false;
|
boolean ignoreValidate;
|
||||||
boolean mergeResult = true;
|
boolean mergeResult;
|
||||||
boolean permission = false;
|
boolean permission;
|
||||||
|
boolean needToken = false;
|
||||||
ApiMapping apiMapping = method.getAnnotation(ApiMapping.class);
|
ApiMapping apiMapping = method.getAnnotation(ApiMapping.class);
|
||||||
if (apiMapping != null) {
|
if (apiMapping != null) {
|
||||||
name = apiMapping.value()[0];
|
name = apiMapping.value()[0];
|
||||||
@@ -45,6 +46,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
ignoreValidate = apiMapping.ignoreValidate();
|
ignoreValidate = apiMapping.ignoreValidate();
|
||||||
mergeResult = apiMapping.mergeResult();
|
mergeResult = apiMapping.mergeResult();
|
||||||
permission = apiMapping.permission();
|
permission = apiMapping.permission();
|
||||||
|
needToken = apiMapping.needToken();
|
||||||
} else {
|
} else {
|
||||||
ApiAbility apiAbility = this.findApiAbilityAnnotation(method);
|
ApiAbility apiAbility = this.findApiAbilityAnnotation(method);
|
||||||
if (apiAbility != null) {
|
if (apiAbility != null) {
|
||||||
@@ -52,6 +54,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
ignoreValidate = apiAbility.ignoreValidate();
|
ignoreValidate = apiAbility.ignoreValidate();
|
||||||
mergeResult = apiAbility.mergeResult();
|
mergeResult = apiAbility.mergeResult();
|
||||||
permission = apiAbility.permission();
|
permission = apiAbility.permission();
|
||||||
|
needToken = apiAbility.needToken();
|
||||||
} else {
|
} else {
|
||||||
return super.getCustomMethodCondition(method);
|
return super.getCustomMethodCondition(method);
|
||||||
}
|
}
|
||||||
@@ -75,6 +78,7 @@ public class ApiMappingHandlerMapping extends RequestMappingHandlerMapping imple
|
|||||||
apiMappingInfo.setIgnoreValidate(ignoreValidate);
|
apiMappingInfo.setIgnoreValidate(ignoreValidate);
|
||||||
apiMappingInfo.setMergeResult(mergeResult);
|
apiMappingInfo.setMergeResult(mergeResult);
|
||||||
apiMappingInfo.setPermission(permission);
|
apiMappingInfo.setPermission(permission);
|
||||||
|
apiMappingInfo.setNeedToken(needToken);
|
||||||
logger.info("注册接口,name:" + method + ", version:" + version);
|
logger.info("注册接口,name:" + method + ", version:" + version);
|
||||||
return new ApiMappingRequestCondition(apiMappingInfo);
|
return new ApiMappingRequestCondition(apiMappingInfo);
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ public class ApiMappingInfo {
|
|||||||
private boolean ignoreValidate;
|
private boolean ignoreValidate;
|
||||||
private boolean mergeResult;
|
private boolean mergeResult;
|
||||||
private boolean permission;
|
private boolean permission;
|
||||||
|
private boolean needToken;
|
||||||
|
|
||||||
public ApiMappingInfo(String name, String version) {
|
public ApiMappingInfo(String name, String version) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@@ -68,4 +68,9 @@ public class RouteDefinition {
|
|||||||
* 是否需要授权才能访问
|
* 是否需要授权才能访问
|
||||||
*/
|
*/
|
||||||
private int permission;
|
private int permission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否需要token
|
||||||
|
*/
|
||||||
|
private int needToken;
|
||||||
}
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
package com.gitee.sop.storyweb.controller;
|
||||||
|
|
||||||
|
import com.gitee.sop.servercommon.annotation.ApiMapping;
|
||||||
|
import com.gitee.sop.servercommon.bean.OpenContext;
|
||||||
|
import com.gitee.sop.servercommon.bean.ServiceContext;
|
||||||
|
import com.gitee.sop.storyweb.controller.param.StoryParam;
|
||||||
|
import com.gitee.sop.storyweb.controller.result.StoryResult;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@Slf4j
|
||||||
|
@Api(tags = "故事接口")
|
||||||
|
public class TokenController {
|
||||||
|
|
||||||
|
@ApiMapping(value = "story.token.get", needToken = true/* 设置true,网关会校验token是否存在 */)
|
||||||
|
public StoryResult token(StoryParam story) {
|
||||||
|
OpenContext openContext = ServiceContext.getCurrentContext().getOpenContext();
|
||||||
|
String appAuthToken = openContext.getAppAuthToken();
|
||||||
|
StoryResult result = new StoryResult();
|
||||||
|
result.setName("appAuthToken:" + appAuthToken);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,15 +1,13 @@
|
|||||||
package com.gitee.sop.gateway.entity;
|
package com.gitee.sop.gateway.entity;
|
||||||
|
|
||||||
import com.gitee.fastmybatis.core.annotation.LogicDelete;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,6 +61,9 @@ public class ConfigServiceRoute {
|
|||||||
/** 是否需要授权才能访问, 数据库字段:permission */
|
/** 是否需要授权才能访问, 数据库字段:permission */
|
||||||
private Byte permission;
|
private Byte permission;
|
||||||
|
|
||||||
|
/** 是否需要token, 数据库字段:need_token */
|
||||||
|
private Byte needToken;
|
||||||
|
|
||||||
/** 数据库字段:gmt_create */
|
/** 数据库字段:gmt_create */
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
|
|
||||||
|
@@ -54,6 +54,7 @@ public class DbRoutesProcessor implements RoutesProcessor {
|
|||||||
configServiceRoute.setStatus((byte) routeDefinition.getStatus());
|
configServiceRoute.setStatus((byte) routeDefinition.getStatus());
|
||||||
configServiceRoute.setPermission((byte) routeDefinition.getPermission());
|
configServiceRoute.setPermission((byte) routeDefinition.getPermission());
|
||||||
configServiceRoute.setOrder(routeDefinition.getOrder());
|
configServiceRoute.setOrder(routeDefinition.getOrder());
|
||||||
|
configServiceRoute.setNeedToken((byte)routeDefinition.getNeedToken());
|
||||||
configServiceRoute.setServiceId(serviceId);
|
configServiceRoute.setServiceId(serviceId);
|
||||||
return configServiceRoute;
|
return configServiceRoute;
|
||||||
})
|
})
|
||||||
|
@@ -138,6 +138,7 @@ public class Client {
|
|||||||
private Map<String, String> header;
|
private Map<String, String> header;
|
||||||
private boolean ignoreSign;
|
private boolean ignoreSign;
|
||||||
private boolean postJson;
|
private boolean postJson;
|
||||||
|
private String appAuthToken;
|
||||||
private List<HttpTool.UploadFile> uploadFileList;
|
private List<HttpTool.UploadFile> uploadFileList;
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
|
||||||
@@ -229,6 +230,17 @@ public class Client {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置token
|
||||||
|
*
|
||||||
|
* @param appAuthToken 给定的token
|
||||||
|
* @return 返回RequestBuilder
|
||||||
|
*/
|
||||||
|
public RequestBuilder appAuthToken(String appAuthToken) {
|
||||||
|
this.appAuthToken = appAuthToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加文件
|
* 添加文件
|
||||||
*
|
*
|
||||||
@@ -310,6 +322,9 @@ public class Client {
|
|||||||
if (version != null) {
|
if (version != null) {
|
||||||
params.put("version", version);
|
params.put("version", version);
|
||||||
}
|
}
|
||||||
|
if (appAuthToken != null) {
|
||||||
|
params.put("app_auth_token", appAuthToken);
|
||||||
|
}
|
||||||
params.put("format", "json");
|
params.put("format", "json");
|
||||||
params.put("charset", "utf-8");
|
params.put("charset", "utf-8");
|
||||||
params.put("sign_type", "RSA2");
|
params.put("sign_type", "RSA2");
|
||||||
|
@@ -287,6 +287,17 @@ public class AllInOneTest extends TestBase {
|
|||||||
System.out.println("成功次数:" + success);
|
System.out.println("成功次数:" + success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testToken() {
|
||||||
|
Client.RequestBuilder requestBuilder = new Client.RequestBuilder()
|
||||||
|
.method("story.token.get")
|
||||||
|
.version("1.0")
|
||||||
|
.bizContent(new BizContent().add("id", "1").add("name", "葫芦娃"))
|
||||||
|
.appAuthToken("asdfasdfadsf")
|
||||||
|
.httpMethod(HttpTool.HTTPMethod.GET);
|
||||||
|
|
||||||
|
client.execute(requestBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
class BizContent extends HashMap<String, String> {
|
class BizContent extends HashMap<String, String> {
|
||||||
public BizContent add(String key, String value) {
|
public BizContent add(String key, String value) {
|
||||||
this.put(key, value);
|
this.put(key, value);
|
||||||
|
Reference in New Issue
Block a user