深信服 aTrust Open API 接口对接

avatar 2022年02月21日17:48:01 6 3313 views
博主分享免费Java教学视频,B站账号:Java刘哥 ,长期提供技术问题解决、项目定制:本站商品点此

一、业务场景

因为公司用的深信服的 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&timestamp="+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&timestamp=" + 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;
        }
    }

 

 

 

  • 微信
  • 交流学习,资料分享
  • weinxin
  • 个人淘宝
  • 店铺名:言曌博客咨询部

  • (部分商品未及时上架淘宝)
avatar

发表评论

avatar 登录者:匿名
匿名评论,评论回复后会有邮件通知

  

已通过评论:0   待审核评论数:0