一、业务场景
因为公司用的深信服的 vpn 产品 aTrust
我这里有一个需求是,通过接口去调用 aTrust 的 Open API 去给指定的用户添加角色和删除角色。
因为角色关联应用,用户申请 1天的 vpn 权限,我们自动给他加一个 开发办公的角色,等1天到期后,我们会再去把这个 开发办公角色关联删除掉。
关于定时,我们只需要添加一张表即可,记录申请时间,到期时间,申请人
本文主要介绍该产品的 Open API 对接
二、Open API 对接和加密方式 demo
根据 OpenApi使用文档
需要在 header 里传4个参数。
1、生成签名
package com.example.demo;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author liuyanzhao
* @date 2022/1/17 10:56
*/
public class Demo
{
// 根据name查询用户
public static void main(String[] args) throws Exception
{
String signStr = "/api/v1/externalUser/queryUser?name=liuyanzhao&userDirectoryName=测试域";
Long timestamp = System.currentTimeMillis() / 1000;
System.out.println(timestamp);
String nonce = "f5f0fe63-5b3e-4e44-908c-b95758b6d7e4";
System.out.println(nonce);
String signSecret = "appId=8063094&appSecret=0e84eb8a636a4b26954d495e096e06a0×tamp="+timestamp+"&nonce="+nonce;
System.out.println(HMACSHA256( signStr, signSecret));
}
// // 更新用户
// public static void main(String[] args) throws Exception
// {
//
// String body = "{\"name\":\"liuyanzhao\",\"userDirectoryName\":\"测试域\",\"roleIdEditWay\":\"delete\",\"roleIdList\":[\"7fc8f090-8d2e-11ec-b525-d5d6aebac368\"]}";
// String body2 = body.replace("\n", "").replace(" ", "");
// System.out.println(body2);
// String signStr = "/api/v1/externalUser/update?" + body2;
// Long timestamp = System.currentTimeMillis() / 1000;
// System.out.println(timestamp);
// String nonce = "f5f0fe63-5b3e-4e44-908c-b95758b6d7e4";
// System.out.println(nonce);
// String signSecret = "appId=8063094&appSecret=0e84eb8a636a4b26954d495e096e06a0×tamp=" + timestamp + "&nonce=" + nonce;
// System.out.println(HMACSHA256(signStr, signSecret));
// }
public static String HMACSHA256(String data, String key) throws Exception
{
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array)
{
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toLowerCase();
}
}
查询用户
更新用户
三、正式对接代码示例
1、新建 atrust.properties 文件
# Open API 服务地址
openApi.serverUrl=https://127.0.0.1:4433
# Open API appId
openApi.appId=8061212
# Open API appSecret
openApi.appSecret=0e84eb8a636a4b26954d495e096e1222
# Open API AD域名称
openApi.adName=测试域
2、新建 HttpUtil
public class HttpClientUtil
{
public static final int http_ok = 200;// 返回状态码正常
public static final int CONNECTION_TIMEOUT = 5000;// 连接超时
public static final int READDATA_TIMEOUT = 10000;// 数据读取等待超时
public static final int DEFAULT_HTTP_PORT = 80;// http端口
public static final int DEFAULT_HTTPS_PORT = 443;// https端口
private static Log log = LogFactory.getLog(HttpClientUtil.class);
/**
* 无需本地证书keyStore的SSL https带参数请求
*
* @param url
* @param reqMap
* @param encoding
* @return
*/
public static String postSSLUrlWithParams(String url, Map<String, String> reqMap, String encoding)
{
log.info("httpsClient访问开始...");
CloseableHttpClient httpClient = HttpClientUtil.createSSLInsecureClient();
HttpPost post = new HttpPost(url);
// 添加参数
List<NameValuePair> params = new ArrayList<>();
if (reqMap != null && reqMap.keySet().size() > 0)
{
Iterator<Map.Entry<String, String>> iter = reqMap.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry<String, String> entity = iter.next();
params.add(new BasicNameValuePair(entity.getKey(), entity.getValue()));
}
}
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try
{
// 设置客户端请求的头参数getParams已经过时,现在用requestConfig对象替换
// httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,CONNECTION_TIMEOUT);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT)
.setSocketTimeout(READDATA_TIMEOUT).build();
post.setConfig(requestConfig);
// 设置编码格式
post.setEntity(new UrlEncodedFormEntity(params, encoding));
HttpResponse response = httpClient.execute(post);
HttpEntity httpEntity = response.getEntity();
br = new BufferedReader(new InputStreamReader(httpEntity.getContent(), encoding));
String s = null;
while ((s = br.readLine()) != null)
{
sb.append(s);
}
} catch (UnsupportedEncodingException e)
{
log.error("编码格式输入错误", e);
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + encoding);
} catch (ClientProtocolException e)
{
e.printStackTrace();
} catch (IOException e)
{
log.error("读取流文件异常", e);
throw new RuntimeException("读取流文件异常", e);
} catch (Exception e)
{
log.error("通讯未知系统异常", e);
throw new RuntimeException("通讯未知系统异常", e);
} finally
{
if (br != null)
{
try
{
br.close();
} catch (IOException e)
{
log.error("关闭br异常" + e);
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* 无需本地证书keyStore的SSL https带参数请求
*
* @param url
* @param reqMap
* @param encoding
* @return
*/
public static String getSSLUrlWithParams(String url, Map<String, String> reqMap, Map<String, String> headers, String encoding)
{
log.info("httpsClient访问开始...");
CloseableHttpClient httpClient = HttpClientUtil.createSSLInsecureClient();
// 添加参数
List<NameValuePair> params = new ArrayList<>();
if (reqMap != null && reqMap.keySet().size() > 0)
{
Iterator<Map.Entry<String, String>> iter = reqMap.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry<String, String> entity = iter.next();
params.add(new BasicNameValuePair(entity.getKey(), entity.getValue()));
}
}
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try
{
URIBuilder uriBuilder = new URIBuilder(url);
//设置参数
for (Map.Entry<String, String> entry : reqMap.entrySet())
{
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
HttpGet get = new HttpGet(uriBuilder.build());
// 设置客户端请求的头参数getParams已经过时,现在用requestConfig对象替换
// httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,CONNECTION_TIMEOUT);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT)
.setSocketTimeout(READDATA_TIMEOUT).build();
get.setConfig(requestConfig);
// 设置header
for (Map.Entry<String, String> entry : headers.entrySet())
{
get.setHeader(entry.getKey(), entry.getValue());
}
get.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(get);
HttpEntity httpEntity = response.getEntity();
br = new BufferedReader(new InputStreamReader(httpEntity.getContent(), encoding));
String s = null;
while ((s = br.readLine()) != null)
{
sb.append(s);
}
} catch (UnsupportedEncodingException e)
{
log.error("编码格式输入错误", e);
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + encoding);
} catch (ClientProtocolException e)
{
e.printStackTrace();
} catch (IOException e)
{
log.error("读取流文件异常", e);
throw new RuntimeException("读取流文件异常", e);
} catch (Exception e)
{
log.error("通讯未知系统异常", e);
throw new RuntimeException("通讯未知系统异常", e);
} finally
{
if (br != null)
{
try
{
br.close();
} catch (IOException e)
{
log.error("关闭br异常" + e);
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* 无需本地证书keyStore的SSL https带参数请求
*
* @param url
* @param json
* @param encoding
* @return
*/
public static String postSSLUrlWithJson(String url, String json, Map<String, String> headers, String encoding)
{
if (StringUtils.isEmpty(json))
{
json = "{}";
}
log.info("httpsClient访问开始...");
CloseableHttpClient httpClient = HttpClientUtil.createSSLInsecureClient();
HttpPost post = new HttpPost(url);
// 添加参数
List<NameValuePair> params = new ArrayList<>();
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try
{
// 设置客户端请求的头参数getParams已经过时,现在用requestConfig对象替换
// httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,CONNECTION_TIMEOUT);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT)
.setSocketTimeout(READDATA_TIMEOUT).build();
post.setConfig(requestConfig);
// 设置参数和编码格式
post.setEntity(new StringEntity(json, encoding));
// 设置header
for (Map.Entry<String, String> entry : headers.entrySet())
{
post.setHeader(entry.getKey(), entry.getValue());
}
post.setHeader("Content-Type", "application/json");
HttpResponse response = httpClient.execute(post);
HttpEntity httpEntity = response.getEntity();
br = new BufferedReader(new InputStreamReader(httpEntity.getContent(), encoding));
String s = null;
while ((s = br.readLine()) != null)
{
sb.append(s);
}
} catch (UnsupportedEncodingException e)
{
log.error("编码格式输入错误", e);
throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + encoding);
} catch (ClientProtocolException e)
{
e.printStackTrace();
} catch (IOException e)
{
log.error("读取流文件异常", e);
throw new RuntimeException("读取流文件异常", e);
} catch (Exception e)
{
log.error("通讯未知系统异常", e);
throw new RuntimeException("通讯未知系统异常", e);
} finally
{
if (br != null)
{
try
{
br.close();
} catch (IOException e)
{
log.error("关闭br异常" + e);
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* 创建一个SSL信任所有证书的httpClient对象
*
* @return
*/
public static CloseableHttpClient createSSLInsecureClient()
{
try
{
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
{
// 默认信任所有证书
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return true;
}
}).build();
// AllowAllHostnameVerifier: 这种方式不对主机名进行验证,验证功能被关闭,是个空操作(域名验证)
SSLConnectionSocketFactory sslcsf = new SSLConnectionSocketFactory(sslContext,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return HttpClients.custom().setSSLSocketFactory(sslcsf).build();
} catch (KeyManagementException e)
{
e.printStackTrace();
} catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
} catch (KeyStoreException e)
{
e.printStackTrace();
}
return HttpClients.createDefault();
}
}
3、调用 Open API 核心代码
/**
* 初始化 atust 配置
*/
private boolean initAtrustOpenApiConfig()
{
if (StringUtils.isNotEmpty(VPN_OPEN_API_SERVER_URL) &&
StringUtils.isNotEmpty(VPN_OPEN_API_APP_ID) &&
StringUtils.isNotEmpty(VPN_OPEN_API_APP_SECRET) &&
StringUtils.isNotEmpty(AD_NAME))
{
return true;
}
Properties p = new Properties();
InputStream is = null;
try
{
is = VpnOpenApiServiceImpl.class.getResourceAsStream(CONFIG_PATH);
p.load(new InputStreamReader(is, "UTF-8"));
VPN_OPEN_API_SERVER_URL = p.getProperty("openApi.serverUrl");
VPN_OPEN_API_APP_ID = p.getProperty("openApi.appId");
VPN_OPEN_API_APP_SECRET = p.getProperty("openApi.appSecret");
AD_NAME = p.getProperty("openApi.adName");
if (StringUtils.isNotEmpty(VPN_OPEN_API_SERVER_URL) &&
StringUtils.isNotEmpty(VPN_OPEN_API_APP_ID) &&
StringUtils.isNotEmpty(VPN_OPEN_API_APP_SECRET) &&
StringUtils.isNotEmpty(AD_NAME))
{
return true;
} else
{
log.info("atrust配置未配置完整,serverUrl:" + VPN_OPEN_API_SERVER_URL + ",appId:" + VPN_OPEN_API_APP_ID
+ ",appSecret:" + VPN_OPEN_API_APP_SECRET + ",adName:" + AD_NAME);
}
} catch (Exception e)
{
log.error("读取" + CONFIG_PATH + ",初始化属性失败,e:" + e);
} finally
{
try
{
is.close();
} catch (IOException e)
{
log.error("is.close()失败");
}
}
return false;
}
/**
* 查询用户的角色列表
*
* @param username 用户账号
* @param userDirectoryName 域名称,如 测试域
* @return
*/
public List<OpenApiRole> getUserRoleList(String username, String userDirectoryName)
{
Map<String, String> params = new HashMap<>();
params.put("name", username);
params.put("userDirectoryName", userDirectoryName);
List<OpenApiRole> roleList = new ArrayList<>();
StringBuilder url = new StringBuilder(VPN_OPEN_API_SERVER_URL).append(VPN_OPEN_API_QUERY_USER_URL);
StringBuilder urlAndParam = new StringBuilder(VPN_OPEN_API_QUERY_USER_URL);
urlAndParam = urlAndParam.append("?name=").append(username).append("&userDirectoryName=").append(userDirectoryName);
try
{
Map<String, String> headers = buildHeader(urlAndParam.toString());
String responseJson = HttpClientUtil.getSSLUrlWithParams(url.toString(), params, headers, "utf-8");
JSONObject jsonObject = JSONObject.parseObject(responseJson);
log.info("Open API查询外部用户详情,响应:" + jsonObject.toJSONString());
if (jsonObject.getInteger("code") == 0)
{
JSONObject data = jsonObject.getJSONObject("data");
JSONArray dataJSONArray = data.getJSONArray("data");
if (dataJSONArray != null && dataJSONArray.size() > 0)
{
JSONObject user = (JSONObject) dataJSONArray.get(0);
if (user != null && user.getJSONArray("roleList") != null)
{
roleList = JSONObject.parseArray(user.getJSONArray("roleList").toJSONString(), OpenApiRole.class);
}
}
} else
{
log.error("Open API查询外部用户详情,请求失败:" + jsonObject.getString("message"));
}
} catch (Exception e)
{
log.error("调用Open API查询外部用户详情的接口,username:" + username + ", userDirectoryName:" + userDirectoryName + ", 获取角色列表失败:" + e);
}
return roleList;
}
/**
* 查询角色详情
*
* @param roleName 角色名称
* @return
*/
public OpenApiRole getRoleByName(String roleName)
{
Map<String, String> params = new HashMap<>();
params.put("name", roleName);
OpenApiRole openApiRole = null;
StringBuilder url = new StringBuilder(VPN_OPEN_API_SERVER_URL).append(VPN_OPEN_API_QUERY_ROLE_URL);
StringBuilder urlAndParam = new StringBuilder(VPN_OPEN_API_QUERY_ROLE_URL);
urlAndParam = urlAndParam.append("?name=").append(roleName);
try
{
Map<String, String> headers = buildHeader(urlAndParam.toString());
String responseJson = HttpClientUtil.getSSLUrlWithParams(url.toString(), params, headers, "utf-8");
JSONObject jsonObject = JSONObject.parseObject(responseJson);
log.info("Open API查询角色详情,响应:" + jsonObject.toJSONString());
if (jsonObject.getInteger("code") == 0)
{
JSONObject data = jsonObject.getJSONObject("data");
JSONArray dataJSONArray = data.getJSONArray("data");
if (dataJSONArray != null && dataJSONArray.size() > 0)
{
openApiRole = JSONObject.parseObject(((JSONObject) dataJSONArray.get(0)).toJSONString(), OpenApiRole.class);
}
} else
{
log.error("Open API查询角色详情,请求失败:" + jsonObject.getString("message"));
}
} catch (Exception e)
{
log.error("调用Open API查询角色详情的接口,name:" + roleName + "失败:" + e);
}
return openApiRole;
}
/**
* 编辑外部用户
*
* @param username 用户账号
* @param userDirectoryName 域名称,如 测试域
* @return
*/
public boolean updateUserRole(String username, String userDirectoryName, List<String> roleIdList)
{
Map<String, String> params = new HashMap<>();
params.put("name", username);
params.put("userDirectoryName", userDirectoryName);
StringBuilder url = new StringBuilder(VPN_OPEN_API_SERVER_URL).append(VPN_OPEN_API_UPDATE_USER_URL);
StringBuilder urlAndParam = new StringBuilder(VPN_OPEN_API_UPDATE_USER_URL);
String bodyJson = "{\"name\":\"" + username + "\",\"userDirectoryName\":\"" + userDirectoryName + "\",\"roleIdEditWay\":\"set\",\"roleIdList\":" + JSON.toJSONString(roleIdList) + "}";
urlAndParam = urlAndParam.append("?").append(bodyJson);
try
{
Map<String, String> headers = buildHeader(urlAndParam.toString());
String responseJson = HttpClientUtil.postSSLUrlWithJson(url.toString(), bodyJson, headers, "utf-8");
JSONObject jsonObject = JSONObject.parseObject(responseJson);
log.info("Open API编辑外部用户,响应:" + jsonObject.toJSONString());
if (jsonObject.getInteger("code") == 0)
{
log.info("Open API编辑外部用户,操作成功");
return true;
} else
{
log.error("Open API编辑外部用户,请求失败:" + jsonObject.getString("msg"));
return false;
}
} catch (Exception e)
{
log.error("调用Open API编辑外部用户接口,username:" + username + ", userDirectoryName:" + userDirectoryName + ", roleIdList:" + roleIdList.toArray() + ", 获取角色列表失败:" + e);
return false;
}
}
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏