平台JWT接口文档
===
**目录索引:**
- 接口方式
- 接口安全
- 缓存配置
- 接口说明
- 在线接口文档
- 客户端测试代码
- 接口案例
# 平台JWT接口文档
## 一、接口方式
接口调用采用http协议,restful请求方式;
## 二、接口安全
接口安全采用Json web token (JWT)机制,基于token的鉴权机制.
### 1.机制说明
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
### 2.基本流程
流程上是这样的:
(1)用户使用用户名密码来请求服务器
(2)服务器进行验证用户的信息
(3)服务器通过验证发送给用户一个token
(4)客户端存储token,并在每次请求时附送上这个token值(存在head里的参数X-AUTH-TOKEN)
(5)服务端验证token值,并返回数据
![](https://img.kancloud.cn/bd/7b/bd7b7ef2957565e158256366fca6d079_1240x695.png)
### 3.优点
* 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
* 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
* 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
* 它不需要在服务端保存会话信息, 所以它易于应用的扩展
### 4.安全相关
* 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
* 保护好secret私钥,该私钥非常重要。
* 如果可以,请使用https协议
### 5.鉴权TOKEN接口
##### (1)描述
根据用户名和密码获取TOKEN。
##### (2)访问地址
http://域名/rest/tokens
##### (3)访问方式
GET
##### (4)参数
| 参数名| 数据类型| 是否必须| 示例值| 默认值| 描述|
| -------- | ----- | ---- |
| username| String| Y| “admin”| | 用户名|
| password| String| Y| “123456”| | 密码|
##### (5)返回值
成功时,直接返回token字符串。
失败时,直接返回用户账号密码错误!
##### (6)校验规则
无
##### (7)请求示例
请求地址:http://域名/rest/tokens
```
{
"username":"admin",
"password":"123456"
}
```
##### (8)返回示例
```
成功案例:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4YThhYjBiMjQ2ZGM4MTEyMDE0NmRjODE4MTk1MDA1MiIsInN1YiI6ImFkbWluIiwiaWF0IjoxNTExODU0NDE4fQ.
tnILZEivS-6YOX9uqsnCHygh7-XrG_-Sj8vLslNGkdQ
失败案例:
用户账号密码错误!
```
## 三、缓存配置
JWT 验证token采用redis进行缓存,
redis配置文件:src/main/resources/redis.properties
修改redis对应的IP和端口。
```
#redis
redis.host=124.206.91.99
redis.port=6379
redis.pass=
redis.adapter.maxIdle=100
redis.adapter.minIdle=10
redis.adapter.testOnBorrow=true
redis.adapter.testOnReturn=true
redis.adapter.testWhileIdle=true
redis.adapter.numTestsPerEvictionRun=10
redis.adapter.timeBetweenEvictionRunsMillis=60000
```
## 四、接口说明
**注意:**访问除【鉴权TOKEN接口】以外的接口时,都需要访问用户拥有对接口的访问权限,如无权限,将直接返回如下信息:
```
{"message":"您没有该接口的权限!","data":null,"ok":false,"respCode":"-1"}
```
## 五、在线接口文档
集成Swagger-ui 实现在线接口文档,访问地址:
http://localhost:8080/jeecg/swagger/index.html
效果如图:
![](https://img.kancloud.cn/3a/65/3a653c84ac36f59902c8b05b5a9f3c95_1147x571.png)
## 六、客户端测试代码
* 代码示例
```
public static String getToken(String userName,String password){
String url = "http://localhost:8080/jeecg/rest/tokens?username="+userName+"&password="+password;
String token= JwtHttpUtil.httpRequest(url, "POST", null);
return token;
}
//获取黑名单列表
public static JSONObject getBlackList(String token){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "GET", null,token);
return resp;
}
//创建黑名单
public static JSONObject createBlackList(String token,String json){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "POST", json,token);
return resp;
}
//更新黑名单
public static JSONObject updateBlackList(String token,String json){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "PUT", json,token);
return resp;
}
//删除黑名单
public static JSONObject deleteBlackList(String token,String id){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController/"+id;
JSONObject resp= JwtHttpUtil.httpRequest(url, "DELETE", null,token);
return resp;
}
//查询黑名单
public static JSONObject getBlackList(String token,String id){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController/"+id;
JSONObject resp= JwtHttpUtil.httpRequest(url, "GET", null,token);
return resp;
```
* 参考源码:
```
package org.jeecgframework.jwt.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import org.jeecgframework.core.util.LogUtil;
import com.alibaba.fastjson.JSONObject;
/**
* JWT 客户端
* @author qinfeng
*
*/
public class JwtHttpUtil {
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr, String sign) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
HttpURLConnection httpUrlConn = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setRequestProperty("X-AUTH-TOKEN", sign);
httpUrlConn.setRequestProperty("Accept", "*/*");
httpUrlConn.setRequestProperty("Content-Type", "application/json");
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
System.out.println(buffer.toString());
jsonObject = JSONObject.parseObject(buffer.toString());
// jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
LogUtil.info("Weixin server connection timed out.");
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("https request error:{}" + e.getMessage());
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("http close error:{}" + e.getMessage());
}
}
return jsonObject;
}
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
String res = "";
StringBuffer buffer = new StringBuffer();
HttpURLConnection httpUrlConn = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setRequestProperty("Accept", "text/plain");
httpUrlConn.setRequestProperty("Content-Type", "application/json");
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
res = buffer.toString();
System.out.println(res);
// jsonObject = JSONObject.parseObject(buffer.toString());
// jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
LogUtil.info("Weixin server connection timed out.");
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("https request error:{}" + e.getMessage());
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("http close error:{}" + e.getMessage());
}
}
return res;
}
}
```
```
package org.jeecgframework.test.demo;
import org.jeecgframework.jwt.util.JwtHttpUtil;
import com.alibaba.fastjson.JSONObject;
/**
* jeecg jwt
* 接口客户端调用demo
* @author qinfeng
*
*/
public class JwtRestfulClientDemo {
public static String getToken(String userName,String password){
String url = "http://localhost:8080/jeecg/rest/tokens?username="+userName+"&password="+password;
String token= JwtHttpUtil.httpRequest(url, "POST", null);
return token;
}
//获取黑名单列表
public static JSONObject getBlackList(String token){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "GET", null,token);
return resp;
}
//创建黑名单
public static JSONObject createBlackList(String token,String json){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "POST", json,token);
return resp;
}
//更新黑名单
public static JSONObject updateBlackList(String token,String json){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController";
JSONObject resp= JwtHttpUtil.httpRequest(url, "PUT", json,token);
return resp;
}
//删除黑名单
public static JSONObject deleteBlackList(String token,String id){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController/"+id;
JSONObject resp= JwtHttpUtil.httpRequest(url, "DELETE", null,token);
return resp;
}
//查询黑名单
public static JSONObject getBlackList(String token,String id){
String url = "http://localhost:8080/jeecg/rest/tsBlackListController/"+id;
JSONObject resp= JwtHttpUtil.httpRequest(url, "GET", null,token);
return resp;
}
public static void main(String[] args) {
String token = getToken("interfaceuser","123456");
// String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZG1pbiIsInN1YiI6ImFkbWluIiwiaWF0IjoxNTExODU5NjM2fQ.Emfe8VZKA_L33jaW8ZUtVFVDEin83Np_d3gKlPIZryE";
// System.out.println(token);
//添加黑名单
// JSONObject jsonObject=new JSONObject();
// jsonObject.put("ip","192.168.1.2");
// System.out.println("======添加黑名单======="+createBlackList(token,jsonObject.toJSONString()));
//更新黑名单
// JSONObject jsonObject=new JSONObject();
// jsonObject.put("id","402881ee6001da57016001dc13110001");
// jsonObject.put("ip","192.168.0.111");
// System.out.println("======更新黑名单======="+updateBlackList(token,jsonObject.toJSONString()));
//删除黑名单
// System.out.println("======删除黑名单======="+deleteBlackList(token,"402881ee6001da57016001dc13110001"));
//查询黑名单
// System.out.println("======查询黑名单======="+getBlackList(token,"402881ee6001e873016001f369f40008"));
//获取黑名单列表
System.out.println("======获取黑名单列表======="+getBlackList(token));
}
}
```
## 七、接口案例
### 1.创建黑名单信息接口
* 描述
创建黑名单信息接口,黑名单为单表。
* 访问地址
http://域名/rest/tsBlackListController
* 访问方式
POST
* 参数(详见excel)
![](https://img.kancloud.cn/58/0e/580e6a56f3668c3a3581b5e428f84e47_701x93.png)
* 返回值
| 参数名| 描述|
| -------- | ----- | ---- |
| respCode| 返回码(见附录1接口返回信息列表)|
| respMsg| 返回信息(见附录1接口返回信息列表)|
| data| 返回结果(NULL)|
| ok| 状态|
* 校验规则
1. 接口中涉及日期时间的字段,要求格式化为字符串传递,日期格式为“YYYY-MM-dd”,时间格式为“YYYY-MM-dd HH:mm:ss”。
* 请求示例
请求地址:http://域名/rest/tsBlackListController
参数如下:
注意:创建企业无需传id,子表无需传id和企业id,这些都会在后台生成,必需要传入的是来源id和来源表。
```
{
"ip": "192.1.1.1",
……(省略信息其他字段)
}
```
* 返回示例
```
成功案例:
{
"respCode":"0",
" respMsg":"成功"
}
失败案例:
{
"respCode":"-1",
"respMsg":"黑名单创建失败"
}
```
### 2.查询黑名单信息接口
* 描述
根据id查询或查询黑名单信息接口。
* 访问地址
根据id查询:http://域名/rest/tsBlackListController/get/{id}
* 访问方式
GET
* 参数
无
* 返回值
| 参数名| 描述|
| -------- | ----- | ---- |
| respCode| 返回码(见附录1接口返回信息列表)|
| respMsg| 返回信息(见附录1接口返回信息列表)|
| data| 返回结果(结构参照创建企业接口的参数,具体字段参照excel)|
| ok| 状态|
* 校验规则
* 请求示例
* 请求地址:http://域名/rest/tsBlackListController/get/297e7ae15f7f7f7e015f7fb0f57e0040
* 返回示例
```
成功案例:
{
"message": "成功",
"data": {
"id": "402881f15e751d2a015e75212c570005",
"createBy": "admin",
"updateBy": "",
"bpmStatus": "1",
"ip": "111.193.210.4",
"createName": "管理员",
"createDate": "2017-09-12 16:07:41",
"updateName": "",
"updateDate": null,
"sysOrgCode": "A03",
"sysCompanyCode": "A03"
},
"respCode": "0",
"ok": true
}
```
```
失败案例:
{"data":null,"respCode":"-1","respMsg":"根据所传id查询无结果"}
```
### 3.修改黑名单信息接口
* 描述
根据id修改
* 访问地址
http://域名/rest/tsBlackListController/update/{id}
* 访问方式
PUT
* 参数
![](https://img.kancloud.cn/9d/58/9d588866cae7ea5b69b5a4af13c9ffe6_949x188.png)
* 返回值
| 参数名| 描述|
| -------- | ----- | ---- |
| respCode| 返回码(见附录1接口返回信息列表)|
| respMsg| 返回信息(见附录1接口返回信息列表)|
| data| 返回结果(NULL)|
| ok| 状态|
* 校验规则
1.通过校验主表的字段:来源id和来源表验证数据唯一性。
* 请求示例
请求地址:http://域名/rest/tsBlackListController/update/402881f15f811877015f8124ca1c0002
参数如下:
```
{
"id": "402881e75f94878e015f94896bb80002",
"ip": "1.1.1.1"
}
```
* 返回示例
```
成功案例:
{
"respCode":"0",
"respMsg":"成功"
}
失败案例:
{
"respCode":"-1",
"respMsg":"输入ID无效,重复输入"
}
```
### 4.删除黑名单接口
* 描述
根据id删除
* 访问地址
http://域名/rest/tsBlackListController/delete/{id}
* 访问方式
DELETE
* 参数
无
* 返回值
| 参数名| 描述|
| -------- | ----- | ---- |
| respCode| 返回码(见附录1接口返回信息列表)|
| respMsg| 返回信息(见附录1接口返回信息列表)|
| data| 返回结果(NULL)|
| ok| 状态|
* 校验规则
无
* 请求示例
请求地址:http://域名/rest/tsBlackListController/delete/297e7ae15f7f7f7e015f7fb0f57e0040
* 返回示例
```
成功案例:
{
"respCode":"0",
"respMsg":"成功"
}
失败案例:
{
"respCode":"-1",
"respMsg":"输入ID无效,重复输入"
}
```
**附录1:**
接口返回CODE
| code| msg| 说明| 解决方案|
| --- | --- | --- |
| 0| SUCCESS| 成功| |
| -1| ERROR| 无接口访问权限| |
| 1000| VALID_ERROR| 验证失败| |
| r0001| SAVE_SUCCESS| 写入成功| |
| r0002| UPDATE_SUCCESS| 更新成功| |
| r0003| REMOVE_SUCCESS| 删除成功| | |
- 总体介绍
- 快速了解
- 平台优势
- 技术支持
- 社区荣誉
- 开发环境准备
- JEECG私服Maven
- 代码结构说明
- 入门开发环境搭建
- 开发工具
- 代码生成器使用
- GUI代码生成器
- Online代码生成器
- P3插件代码生成器
- 代码生成器配置
- 功能介绍
- 权限开发手册
- Online开发权限
- Online表单访问规则
- 列表按钮权限控制
- 列表数据权限控制
- 页面表单权限控制(一对多表)
- 页面表单权限控制(单表)
- 其他
- 二级管理员手册
- 接口权限配置
- 平台权限设计总览
- 编码开发方式
- 列表按钮权限用法
- 列表数据权限用法
- 数据权限自定义SQL
- 表单权限用法
- UI标签库文档
- AuthFilter(页面权限标签)
- Autocomplete(自动补全标签)
- BaseTag(样式和JS引入标签)
- Choose(弹出选择标签)
- ComboTree(下拉树形选择框)
- Datagrid(数据列表标签)
- DepartSelectTag(部门树选择标签)
- DictSelect(数据字典下拉选择框)
- FormValidation(表单提交及验证标签)
- HasPermissionTag(页面权限标签)
- Menu(左侧菜单生成标签)
- MutiLang(国际化标签)
- OrgSelectTag(部门树列表选择标签)
- SelectZTree(Ztree树控件)
- Tabs(选项卡父标签)
- TreeSelectTag树分类标签
- Upload(上传标签)
- UserSelectTag(用户选择标签)
- WebUploader(上传标签)
- 查询构造器
- 查询过滤器
- 高级查询构造器
- 专题功能介绍
- 国际化使用
- 多数据源使用
- 定时任务
- 平台JWT接口文档
- 消息中心
- Online在线开发
- Online二次开发
- Online代码生成
- Online唯一性校验配置
- Online查询机制(数据权限)
- Online树形表单配置
- Online表单填值规则
- Online表单对外接口
- Online表单控件
- Online表单配置
- Online表单高级应用
- Online报表开发
- Online图形报表配置
- Online数据报表配置
- Online移动报表配置
- 自定义表单设计
- 自定义表单权限
- 列表空间权限控制
- 功能介绍
- 常规控件权限控制
- 自定义表单配置
- 自定义表单二次开发
- 自定义表单控件
- 自定义表单数据源
- 自定义表单模板
- 自定义表单配置
- 自定义表单高级应用
- 表单数据维护
- 附录小技巧
- datagrid扩展属性用法
- Formvalid新增属性tiptype的使用
- JEECG单点集成文档
- Jeecg定时任务开发
- JEECG常见问题贴
- Redis与Ehcache切换文档
- Toolbar自定义js参数规则
- UI标签规则
- 列表多表头的设计
- 列表拓展字段展示
- 列表自定义查询条件
- 员工入职开发规范文档V1.0
- 数据列表合计功能
- 登录权限拦截器排除方法
- 组织机构导入功能使用说明
- 表单字段重复校验方法
- JEECG新技术
- 新版UI技术方案