文章目录
- IPass应用集成平台token授权接入
- 1.接入流程图:
- 2.功能设计:
- 3.测试要点:
IPass应用集成平台token授权接入
1.接入流程图:
功能业务流程描述:
a.调用方从redis获取应用集成平台授权token
b.如果没有拿到,从应用集成平台获取token并更新
c.如果拿到了,但是调用提示token失效,需要返回b,继续获取新的token(可重试)后,往下执行d
d.业务接口携带新的token调用接口
2.功能设计:
-
OkHttpUtils工具类
package com.tn.mdm.common.utils.http; import com.tn.mdm.common.utils.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.net.*; public class OkHttpUtils { private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); public static final RequestConfig queryRequestConfig = RequestConfig.custom(). setConnectionRequestTimeout(60000). // 指从连接池获取连接的timeout setConnectTimeout(60000). // 指客户端和服务器建立连接的timeout, setSocketTimeout(60000). // 指客户端和服务器建立连接后,客户端从服务器读取数据的timeout,超出后会抛出SocketTimeOutException build(); public static String sendGet(String url, String param, String identityToken) { StringBuilder result = new StringBuilder(); BufferedReader in = null; URLConnection connection = null; try { String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; URL realUrl = new URL(urlNameString); connection = realUrl.openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.setRequestProperty("identitytoken", identityToken); connection.connect(); in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result.append(line); } } catch (ConnectException e) { log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); } catch (SocketTimeoutException e) { log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); } catch (IOException e) { log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); if (connection instanceof HttpURLConnection) { int responseCode = 0; try { responseCode = ((HttpURLConnection) connection).getResponseCode(); } catch (IOException ioException) { ioException.printStackTrace(); } if (responseCode == 401) { // 身份验证失败 InputStream errorStream = ((HttpURLConnection) connection).getErrorStream(); if (errorStream != null) { try { in = new BufferedReader(new InputStreamReader(errorStream, "UTF-8")); } catch (UnsupportedEncodingException unsupportedEncodingException) { unsupportedEncodingException.printStackTrace(); } StringBuilder errorMsgBuilder = new StringBuilder(); String line = null; while (true) { try { if (!((line = in.readLine()) != null)) break; } catch (IOException ioException) { ioException.printStackTrace(); } errorMsgBuilder.append(line); } String errorMsg = errorMsgBuilder.toString(); result.append(errorMsg); } } } } catch (Exception e) { System.out.println("异常"); } finally { try { if (in != null) { in.close(); } } catch (Exception ex) { log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); } } return result.toString(); } public static String sendPost(String url, String param, String identityToken) { PrintWriter out = null; BufferedReader in = null; StringBuilder result = new StringBuilder(); try { log.info("sendPost - {}", url); URL realUrl = new URL(url); URLConnection conn = realUrl.openConnection(); conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn.setRequestProperty("Accept-Charset", "utf-8"); conn.setRequestProperty("contentType", "utf-8"); conn.setRequestProperty("identitytoken", identityToken); conn.setDoOutput(true); conn.setDoInput(true); out = new PrintWriter(conn.getOutputStream()); out.print(param); out.flush(); in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); String line; while ((line = in.readLine()) != null) { result.append(line); } log.info("recv - {}", result); } catch (ConnectException e) { log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); } catch (SocketTimeoutException e) { log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); } catch (IOException e) { log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); // 身份验证失败返回失败信息处理同上 } catch (Exception e) { log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); } finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); } } return result.toString(); } }
-
获取/更新 token的工具类
package com.tn.mdm.common.utils.token; import com.alibaba.fastjson.JSONObject; import com.tn.common.tools.exception.base.BusinessException; import com.tn.mdm.common.utils.http.HttpUtils; import org.springframework.data.redis.core.RedisTemplate; public class TokenUtils { private RedisTemplate<String, String> redisTemplate; private String redisTokenKey; private String host; // 服务器地址 private String loginUrl; // 登录地址无需修改 private String userId; // 在API平台中注册的帐号 private String password; // 帐号的密码,可用md5进行加密一次 private String token; public TokenUtils(RedisTemplate<String, String> redisTemplate, String redisTokenKey, String host, String loginUrl, String userId, String password) { this.redisTemplate = redisTemplate; this.host = host; this.loginUrl = loginUrl; this.userId = userId; this.password = password; this.redisTokenKey = redisTokenKey; } // 从缓存获取token public String getTokenFromRedis() { token = redisTemplate.opsForValue().get(redisTokenKey); return token; } // 更新缓存token public void updateTokenToRedis(String newToken) { redisTemplate.opsForValue().set(redisTokenKey, newToken); } // 从应用集成平台获取新的token public String getNewTokenFromPlatform() { int maxRetryTimes = 2; int retryCount = 0; String result = null; while (retryCount <= maxRetryTimes) { // 获取token result = HttpUtils.sendPost(loginUrl, "userName=" + userId + "&password=" + password); JSONObject jsonObject = JSONObject.parseObject(result); String state = String.valueOf(jsonObject.get("state")); if (state != null && state.equals("false")) { retryCount++; continue; } else { token = (String) jsonObject.get("identitytoken"); return token; } } // 重试次数超过最大重试次数 throw new BusinessException("系统登录失败" + result + retryCount); } }
-
业务接口执行获取redis token,如果业务接口调用返回token失效,需要重新拿取token并重试
@Override public ResultResponse test(String orgId) { String param = "orgId=" + orgId; String sign = null; try { sign = "&sign=" + Md5Utils.md5(param, crmsConfig.getMd5passwd()); } catch (Exception e) { throw new RuntimeException(e); } TokenUtils tokenUtils = new TokenUtils(redisCache.redisTemplate, "iPass_token", iPassConfig.getHost(), iPassConfig.getLoginUrl(), iPassConfig.getUserId(), iPassConfig.getPassword()); // 从缓存获取token String identityToken = tokenUtils.getTokenFromRedis(); if (StringUtils.isEmpty(identityToken)) { // 缓存中没有 identityToken = tokenUtils.getNewTokenFromPlatform(); tokenUtils.updateTokenToRedis(identityToken); } // 缓存中有 String result = OkHttpUtils.sendGet(iPassConfig.getTest(), param + sign, identityToken); JSONObject jsonObject = JSONObject.parseObject(result); // 如果调用token失效 if (jsonObject.containsKey("msg")) { if (jsonObject.get("msg").equals("AppKey认证失败")) { identityToken = tokenUtils.getNewTokenFromPlatform(); tokenUtils.updateTokenToRedis(identityToken); result = OkHttpUtils.sendGet(iPassConfig.getTest(), param + sign, identityToken); jsonObject = JSONObject.parseObject(result); } } return ResultResponse.success(jsonObject.get("data")); }
3.测试要点:
以下测试点已验证通过:
- 模拟缓存中有token
- 模拟缓存中无token时,请求获取token
- 模拟缓存中无token时,请求获取token 3次后失败
- 模拟业务调用时缓存中token失效
返回成功:
{
"data": {
"total": 1,
"rows": [
{
"positionName": "苏南大区-9",
"positionId": "3_H3M0H",
"positionUserName": "孙承剑"
}
]
},
"flag": true,
"code": 200,
"error": null,
"message": null
}