一、 接口方式

    接口调用采用http协议,rest请求方式;

二、 接口安全

    接口安全采用Json web token (JWT)机制,基于token的鉴权机制.

1. 机制说明

    基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

2. 基本流程

    流程上是这样的:

        (1) 用户使用用户名密码来请求服务器

        (2) 服务器进行验证用户的信息

        (3) 服务器通过验证发送给用户一个token

        (4) 客户端存储token,并在每次请求时附送上这个token值(存在head里的参数X-AUTH-TOKEN

        (5) 服务端验证token值,并返回数据

 【JEECG技术文档】JEECG平台对外接口JWT应用文档V3.7.2_jeecg

 

3. 优点

  •   因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
  •   因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
  •   便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
  •   它不需要在服务端保存会话信息, 所以它易于应用的扩展

4. 安全相关

  •   不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
  •   保护好secret私钥,该私钥非常重要。
  •   如果可以,请使用https协议

三、 缓存配置

    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"}

1. 鉴权TOKEN接口

    ■描述

        根据用户名和密码获取TOKEN。

    ■访问地址

        http://域名/rest/tokens

    ■访问方式

        GET

    ■参数

参数名

数据类型

是否必须

示例值

默认值

描述

username

String

Y

“admin”

 

用户名

password

String

Y

123456

 

密码

 

    ■返回值

        成功时,直接返回token字符串。

        失败时直接返回用户账号密码错误!

    ■校验规则

        无

    ■请求示例

        请求地址http://域名/rest/tokens

{
    "username":"admin",
    "password":"123456"
}

    ■返回示例

        成功案例:

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4YThhYjBiMjQ2ZGM4MTEyMDE0NmRjODE4MTk1MDA1MiIsInN1YiI6ImFkbWluIiwiaWF0IjoxNTExODU0NDE4fQ.tnILZEivS-6YOX9uqsnCHygh7-XrG_-Sj8vLslNGkdQ

失败案例:

用户账号密码错误!

2. 创建黑名单信息接口

    ■描述

        创建黑名单信息接口,黑名单为单表。

    ■访问地址

        http://域名/rest/tsBlackListController

    ■访问方式

        POST

    ■参数(详见excel)

参数名

数据类型

是否必须

示例值

默认值

描述

ip

String

Y

192.168.1.1

 

 

......

 

 

……省略信息其他字段……


    ■
返回值

参数名

描述

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":"黑名单创建失败"
}

3. 查询黑名单信息接口

    ■描述

        根据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查询无结果"}

4. 修改黑名单信息接口

    ■描述

        根据id修改

    ■访问地址

        http://域名/rest/tsBlackListController/update/{id}

    ■访问方式

        PUT

    ■参数

参数名

数据类型

是否必须

示例值

默认值

描述

id

String

Y

402881f15f811877015f8124ca1c0002

 

 

ip

String

Y

192.168.1.1

 

 

 

 

 

……省略信息其他字段……

    ■返回值

参数名

描述

respCode

返回码(见附录1接口返回信息列表)

respMsg

返回信息(见附录1接口返回信息列表)

data

返回结果(NULL

ok

状态

    ■校验规则

        通过校验主表的字段:来源id和来源表验证数据唯一性。

    ■请求示例

       请求地址http://域名/rest/tsBlackListController/update/402881f15f811877015f8124ca1c0002

       参数如下

{
  "id": "402881e75f94878e015f94896bb80002",
  "ip": "1.1.1.1"

}

    ■返回示例

成功案例:
{
    "respCode":"0",
    "respMsg":"成功"
}

失败案例:
{
    "respCode":"-1",
    "respMsg":"输入ID无效,重复输入"
}

5. 删除黑名单接口

    ■描述

        根据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无效,重复输入"
}

五、 客户端测试代码

    代码示例

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.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));
	}

}
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;
	}

}



  • 附录1:接口返回CODE

code

msg

说明

解决方案

0

SUCCESS

成功

 

-1

ERROR

无接口访问权限

 

1000

VALID_ERROR

验证失败

 

r0001

SAVE_SUCCESS

写入成功

 

r0002

UPDATE_SUCCESS

更新成功

 

r0003

REMOVE_SUCCESS

删除成功