目录
前言
一、黄金段位接口交互
二、钻石段位接口交互设计
1.接口文档定义
2.工具类以及demo提供
a.调用方部分代码
b.被调用方
三.星耀段位接口访问设计
1.在钻石段位的基础上,进行sdk的封装
a.maven引入
b.sdk包含工具类
四.王者段位接口访问设计
1.开发详情
2.项目结构
3.系统侧使用
4.源码下载
总结
前言
在系统开发过程中,系统与系统之间往往不是完全独立的,需要进行互相调用
黄金段位:直接http访问api接口,获取相关数据
钻石段位:定义接口规范,发放授权,api接口需要认证授权才能访问
星耀段位:提供sdk客户端,封装调用api接口所需要的加解密以及http访问的工具类
王者段位:sdk进一步封装,封装成近似本地调用的api接口,调用方只需配置appId,appSecret,接口域名即可,采用springboot自动装配,开发自己的starter
一、黄金段位接口交互
public String doPost(String host, String uri, String body, String method) {
try {
String address = host + uri;
URL restServiceURL = new URL(address);
HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
httpConnection.setRequestMethod(method);
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setRequestProperty("Content-Type", "application/json");
OutputStream outputStream = httpConnection.getOutputStream();
outputStream.write(body.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
if (httpConnection.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP outor code : " + httpConnection.getResponseCode());
}
BufferedReader responseBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream(), "UTF-8"));
StringBuilder output = new StringBuilder();
do {
output.append(responseBuffer.readLine());
} while (responseBuffer.read() != -1);
httpConnection.disconnect();
return output.toString();
} catch (Exception e) {
LOGGER.error("请求post接口报错:{}", e);
}
return null;
}
二、钻石段位接口交互设计
1.接口文档定义
账号:appId; 授权密钥:appSecret;http每次请求header中需要添加appId、randomcode、timestamp、encodekey、sign五个参数,接口将使用这五个参数进行鉴权判断请求方式是否可以使用当前API
序号
参数名
参数类型 值 描述
值(样例)
1
appId
String 必填 授权帐号
liangxi.zeng
2
randomcode
String 必填 随机生成的字符串(每次可不相同)
2sd4TeSk
3
timestamp
String 必填 当前时间戳
20150917160500
4
encodekey
String 必填 前三个参数拼在一起后加上SIM授权的密钥appSecret作为salt使用SHA-256算法进行加密
8729e01cb547sdc3ea645aaa9f8493ab251e5ef32c3d6628cf85f985319145e3
5
sign
String 必填 签名信息,采用MD5加密,计算公式接口:sign=MD5(uri&body&appSecret),有些接口可能没有body,参数是在URL中,则将body置为空串进行签名
6
appSecret String 必填 加解密双方约定自定义的字符串,用作加密,不能直接放入header
o10ympt70x8gqas8hpoctopk3lwrdfd
7 Content-Type String 必填 参数提交方式 application/Json
2.工具类以及demo提供
a.调用方部分代码
加解密工具类DigestUtils
publicvoid setHeader(HttpURLConnection httpConnection,String uri,String body,String method) throws ProtocolException {
httpConnection.setRequestMethod(method);
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setRequestProperty("Content-Type", "application/json");
httpConnection.setRequestProperty("appId", appId);
String randomCode = RandomStringUtils.random(16, true, true);
httpConnection.setRequestProperty("randomcode", randomCode);
String dateNow = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
httpConnection.setRequestProperty("timestamp", dateNow);
//加密
String encodeKey = DigestUtils.sha256Hex(StringUtils.join(appUser, randomCode, dateNow, "{", privateKey, "}"));
httpConnection.setRequestProperty("encodekey", encodeKey);
//签名
String sign = DigestUtils.md5Hex(StringUtils.join(uri, "&", body, "&", privateKey));
httpConnection.setRequestProperty("sign", sign.toUpperCase(Locale.ROOT));
}
public String doPost(String host, String uri, String body, String method) {
try {
String address = host + uri;
URL restServiceURL = new URL(address);
HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
//设置加解密参数认证参数
setHeader(httpConnection,url,body,method);
OutputStream outputStream = httpConnection.getOutputStream();
outputStream.write(body.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
if (httpConnection.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP outor code : " + httpConnection.getResponseCode());
}
BufferedReader responseBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream(), "UTF-8"));
StringBuilder output = new StringBuilder();
do {
output.append(responseBuffer.readLine());
} while (responseBuffer.read() != -1);
httpConnection.disconnect();
return output.toString();
} catch (Exception e) {
LOGGER.error("请求post接口报错:{}", e);
}
return null;
}
b.被调用方
对请求头里传入的参数进行一一校验即可,设计成过滤器拦截,提供给外部的接口都需要认证鉴权
三.星耀段位接口访问设计
1.在钻石段位的基础上,进行sdk的封装
a.maven引入
<dependency>
<groupId>com.tcl.api.auth</groupId>
<artifactId>auth-util</artifactId>
<version>2.2.0-RELEASE<</version>
</dependency>
b.sdk包含工具类
/**
* api 访问工具类
* @author liangxi.zeng
*/
@Slf4j
public class ApiHttpUtils {
/**
* 设置请求同
* @param httpConnection
* @param uri
* @param appId
* @param body
* @param method
* @throws ProtocolException
*/
private static void setRequestHeader(HttpURLConnection httpConnection
, String uri,String appId,String appSecret
, String body
, String method) throws ProtocolException {
httpConnection.setRequestMethod(method);
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setRequestProperty("Content-Type", "application/json");
httpConnection.setRequestProperty("appuser", appId);
String randomCode = RandomStringUtils.random(16, true, true);
httpConnection.setRequestProperty("randomcode", randomCode);
log.debug("randomcode:{}", randomCode);
String dateNow = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss'Z'");
log.debug("dateNow:{}", dateNow);
httpConnection.setRequestProperty("timestamp", dateNow);
//加密
String encodeKey = DigestUtils.sha256Hex(StringUtils.join(appId, randomCode, dateNow, "{", appSecret, "}"));
log.debug("encodeKey:{}", encodeKey);
httpConnection.setRequestProperty("encodekey", encodeKey);
//签名
String sign = DigestUtils.md5Hex(StringUtils.join(uri, "&", body, "&", appSecret));
log.debug("sign:{}", sign);
httpConnection.setRequestProperty("sign", sign.toUpperCase(Locale.ROOT));
}
/**
* 发送post请求
* @param host
* @param uri
* @param body
* @return
*/
public static String doPost(String host, String uri, String body
,String appId,String appSecret) {
try {
String address = host + uri;
log.debug("appuser:{},privateket:{},address:{}", appId, appSecret,address);
URL restServiceURL = new URL(address);
HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
setRequestHeader(httpConnection,uri,body,appId,appSecret,"POST");
return getResponse(httpConnection,body);
} catch (Exception e) {
log.error("请求idm post接口报错:{}", e);
}
return null;
}
/**
* 发送post请求
* @param host
* @param uri
* @param body
* @return
*/
public static String doGet(String host, String uri, String body
,String appId,String appSecret) {
try {
String address = host + uri;
log.debug("appuser:{},privateket:{},address:{}", appId, appSecret,address);
URL restServiceURL = new URL(address);
HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
setRequestHeader(httpConnection,uri,body,appId,appSecret,"GET");
return getResponse(httpConnection,body);
} catch (Exception e) {
log.error("请求idm post接口报错:{}", e);
}
return null;
}
/**
* 获取响应内容
* @param httpConnection
* @param body
* @return
* @throws IOException
*/
private static String getResponse(HttpURLConnection httpConnection,String body) throws IOException {
OutputStream outputStream = httpConnection.getOutputStream();
outputStream.write(body.getBytes(StandardCharsets.UTF_8));
outputStream.flush();
if (httpConnection.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP outor code : " + httpConnection.getResponseCode());
}
BufferedReader responseBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream(), "UTF-8"));
StringBuilder output = new StringBuilder();
do {
output.append(responseBuffer.readLine());
} while (responseBuffer.read() != -1);
httpConnection.disconnect();
return output.toString();
}
}
四.王者段位接口访问设计
1.开发详情
a.基于springboot的spring.factories开发自己的starter
b.采用openFeign实现http远程接口访问
c.用FeignRequestInterceptor完成请求头的权限认证参数放入
2.项目结构
3.系统侧使用
api:
auth:
appId: 12323
appSecret: lakdsjlajdsljajskdjf
domain: https://sp.tcl.com/portal/
<dependency>
<groupId>com.tcl.ea.zenglx</groupId>
<artifactId>api-auth-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@Service
public class RemoteDeal {
@Autowired
private ApiClient apiClient;
//获取用户信息
public User getUserInfo() {
return apiClient.getUserInfo();
}
}
4.源码下载
api认证源码
总结
1.发起http请求的开源框架有, Forest,httpClient,feign,OKHttp等
2.开发组件需要了解spring的生命周期,各种特性,springboot的各种特性