IntelligentRecognition/ah-jjsp-service/.svn/pristine/e1/e145813f5e060e66e9a7b4b74a8...

369 lines
17 KiB
Plaintext
Raw Normal View History

2024-05-24 16:09:40 +08:00
package com.securityControl.auth.igwUtils;
import com.aostarit.sgid.agent.EncryptHelper;
import com.aostarit.smcrypto.Sm3Utils;
import com.google.gson.JsonObject;
import com.securityControl.auth.igwUtils.EnDecryptUtil;
import com.securityControl.auth.igwUtils.InterfaceEnv;
import com.securityControl.auth.igwUtils.SerUtil;
import com.securityControl.auth.pojo.*;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 单点登录(新)-二级应用获取用户信息demo
* <p>
* {"code":"29547","message":"error","data":"Get ISC user code info by wechat code failure "}
* 出现类似信息表示code已被消费或者code错误需要从i国网内重新获取
*
* @author shimengran
*/
public class IgwSingleSignOn {
private static CloseableHttpClient CLIENT;
static {
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setConnectionRequestTimeout(30000)
.setSocketTimeout(30000)
.build();
TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
SSLContext sslContext;
try {
sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
LayeredConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
Registry<ConnectionSocketFactory> sfr = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", csf != null ? csf : SSLConnectionSocketFactory.getSocketFactory()).build();
PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(sfr);
CLIENT = HttpClients.custom().setSSLSocketFactory(csf)
.setConnectionManager(pollingConnectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}
private static ResponseHandler<String> RESPONSE_HANDLER = new BasicResponseHandler();
// --> isc app id
private static String ISC_APP_ID = "424ffb874241409c8a7d0350f103513f";
// --> signKey
private static String SM2_PRIVATE_KEY = "00D515EE353393AD2CE9BF0AD17A5CC76E90B335143CD3ABF578718DD13369DACD";
// --> isc secret
private static String SM4_KEY = "f1bc301b044244b495973e156f342fbd";
public static void main(String[] args) {
// 企信换取的CODE,每个code只能被消费一次
String code = "LlkvHmalObT6uYZYK-jHuw0Avsji0arWOpFkEKmbmpo";
// 以下两个获取流程取其中一个使用,网省非总部应用建议使用第二个流程
// [流程1] -> 一级应用以 企信换取的CODE 直接获取用户信息
// ISCUser userInfo = getUserInfoByIgwCode(code, ISC_APP_ID, SM4_KEY, SM2_PRIVATE_KEY, InterfaceEnv.UAT);
// System.out.println(SerUtil.toJson(userInfo));
// [流程2] -> 二级应用(省侧)获取用户信息流程
// 注意isc用户id,如果之前用的二级应用的相关接口且使用了isc用户id或组织id相关字段建议使用该接口替换。
// UserInfo userInfo = provinceApplicationGetUserInfo(code, ISC_APP_ID, SM4_KEY, SM2_PRIVATE_KEY, InterfaceEnv.UAT);
String accessToken = getAccessToken("ec94e81f643d47569b2710c07ded639d", "075de29b69dd4e77a1fba981de334f28", "00DC1179A380376AC9175E34F09B8833E8C5DF4968F9904364F2C6B45DCFC61B59", InterfaceEnv.PRODUCT);
}
private static ISCUser getUserInfoByIgwCode(String code, String iscAppId, String sm4Key, String sm2PrivateKey, InterfaceEnv env) {
String reqUrl = env == InterfaceEnv.UAT ? "https://igw.isgcc.net:18443/proxy/getUserByIgwCode" : "https://id.sgcc.com.cn:10443/igwmobile/proxy/getUserByIgwCode";
IgwCodeUserParams params = new IgwCodeUserParams();
params.setCODE(code);
params.setAppId(iscAppId);
CommonResult commonResult = postRequestJson(reqUrl, params, CommonResult.class, null);
System.out.println(SerUtil.toJson(commonResult));
String data = commonResult.getData();
if (data == null) {
return null;
}
try {
String userInfo = EnDecryptUtil.transferDecrypt(data, sm4Key, sm2PrivateKey);
System.out.println(userInfo);
return SerUtil.fromJson(userInfo, ISCUser.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static UserInfo provinceApplicationGetUserInfo(String unionCode, String iscAppId, String sm4Key, String sm2PrivateKey, InterfaceEnv env) {
try {
// !!!建议在前端处理, (该接口为总部统一部署,省侧互联网大区服务器如果要访问需要开墙)
// 根据wechatCode获取用户级联编码信息
// String unionCode = getUnionCodeByWechatCode(code, env);
// !!!建议放在后端处理(互联网大区可直接访问)
// 获取密钥信息uat环境和浙江生产环境获取token的方式有所区别此步骤需要环境区分
String accessToken = "";
if (env == InterfaceEnv.UAT) {
accessToken = getAccessToken(iscAppId, sm4Key, sm2PrivateKey, env);
}
// !!!建议放在后端处理(互联网大区可直接访问)
// 根据级联编码获取用户信息
UserInfo userInfo = getUserInfoByUnionCode(unionCode, iscAppId, sm2PrivateKey, accessToken, env);
System.out.println(SerUtil.toJson(userInfo));
return userInfo;
} catch (Exception e) {
// throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException("用户获取失败", e);
}
}
/**
* 根据i国网Code获取用户级联编码信息
*
* @param code i国网Code 该参数从i国网浏览器跳转获取
* @param env
* @return 级联编码
* @throws Exception
*/
private static String getUnionCodeByWechatCode(String code, InterfaceEnv env) throws Exception {
String reqUrl = env == InterfaceEnv.UAT ? "https://igw.isgcc.net:18443/proxy/getUserCodeByWechatCode" : "https://id.sgcc.com.cn:10443/igwmobile/proxy/getUserCodeByWechatCode";
GetUnionCodeParams params = new GetUnionCodeParams();
params.setCODE(code);
params.setAppId(ISC_APP_ID);
CommonResult commonResult = postRequestJson(reqUrl, params, CommonResult.class, null);
String data = commonResult.getData();
String res = EnDecryptUtil.transferDecrypt(data, SM4_KEY, SM2_PRIVATE_KEY);
UnionUserCodeRes unionUserCodeRes = SerUtil.fromJson(res, UnionUserCodeRes.class);
return unionUserCodeRes.getCode();
}
/**
* uat环境获取accessToken
*
* @param appId appid
* @param clientSecret clientSecret isc secret
* @param env 环境参数,用于区分接口差异
* @return accessToken
*/
private static String getAccessToken(String appId, String clientSecret, String sm2PrivateKey, InterfaceEnv env) {
String url = env == InterfaceEnv.UAT ? "https://igw.isgcc.net:18443/zuul/sgid-provider-console/res/iscMincroService/getAccessToken" : "http://tyqxfrontmv.zj.sgcc.com.cn/isc_frontmv_serv/ticket/getAccessToken";
Map<String, String> data = new HashMap<>(16);
data.put("appId", appId);
data.put("clientSecret", clientSecret);
// 第二步创建httpPost对象
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "*/*");
String digest;
try {
if (env == InterfaceEnv.UAT) {
digest = Sm3Utils.encryptFromText(SerUtil.toJson(data));
} else {
digest = EncryptHelper.sign(sm2PrivateKey, SerUtil.toJson(data));
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
httpPost.setHeader("X-Acloud-Data-Sign", digest);
httpPost.setHeader("X-Clientid", appId);
for (Header allHeader : httpPost.getAllHeaders()) {
System.out.println(allHeader.getName() + " : " + allHeader.getValue());
}
// 第三步给httpPost设置JSON格式的参数
// 环境区分
if (env == InterfaceEnv.UAT) {
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
StringEntity requestEntity = new StringEntity(SerUtil.toJson(data), "UTF-8");
requestEntity.setContentEncoding("UTF-8");
httpPost.setEntity(requestEntity);
}
if (env == InterfaceEnv.PRODUCT) {
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
List<BasicNameValuePair> form = new ArrayList<>();
for (String name : data.keySet()) {
form.add(new BasicNameValuePair(name, data.get(name)));
}
UrlEncodedFormEntity entity;
try {
entity = new UrlEncodedFormEntity(form, "utf-8");
for (BasicNameValuePair basicNameValuePair : form) {
System.out.println(basicNameValuePair.getName() + " : " + basicNameValuePair.getValue());
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
httpPost.setEntity(entity);
}
// 第四步发送HttpPost请求获取返回值
// 调接口获取返回值时,必须用此方法
try {
String response = CLIENT.execute(httpPost, RESPONSE_HANDLER);
System.out.println(response);
JsonObject resObj = SerUtil.fromJson(response, JsonObject.class);
if (env == InterfaceEnv.UAT) {
return resObj.getAsJsonObject("data").get("accessToken").getAsString();
} else {
return resObj.get("data").getAsString();
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 根据级联编码获取用户信息
*
* @param unionCode 级联编码
* @param iscAppId 用户appId
* @param signKey sm2private 解密私钥
* @param accessToken 口令
* @return 用户信息
*/
private static UserInfo getUserInfoByUnionCode(String unionCode, String iscAppId, String signKey, String accessToken, InterfaceEnv env) {
GetUserInfoParams getUserInfoParams = new GetUserInfoParams();
getUserInfoParams.setCode(unionCode);
// header里的参数在生产环境不存在
Map<String, String> headers = new HashMap<>(16);
headers.put("X-Clientid", iscAppId);//注册系统时的appId
if (env == InterfaceEnv.UAT) {
try {
headers.put("X-ISC-AccessToken", "Client " + accessToken);
headers.put("X-Acloud-Data-Sign", EncryptHelper.sign(signKey, SerUtil.toJson(getUserInfoParams))); //请求json串的签名串
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
headers.put("Accept", "*/*");
// FIXME: isc接口未给出
String reqUrl = env == InterfaceEnv.UAT ? "https://igw.isgcc.net:18443/sgid-provider-province-identity/identity/getUsersByCode" : "http://tyqxfrontmv.zj.sgcc.com.cn/sgid-provider-province-identity/identity/getUsersByCode";
JsonObject userJsonObj = postRequestJson(reqUrl, getUserInfoParams, JsonObject.class, headers);
JsonObject enUserInfo = userJsonObj.get("data").getAsJsonObject();
try {
return SerUtil.fromJson(SerUtil.toJson(enUserInfo), UserInfo.class);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static <T> T postRequestJson(String url, Object obj, Class<T> resClz, Map<String, String> headers) {
System.out.println("request url : " + url);
System.out.println("request data : " + SerUtil.toJson(obj));
System.out.println("request headers : " + SerUtil.toJson(headers));
String jsonBody = SerUtil.toJson(obj);
StringEntity requestEntity;
try {
requestEntity = new StringEntity(jsonBody, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
requestEntity.setContentType("application/json");
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(requestEntity);
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
if (headers != null && !headers.isEmpty()) {
headers.forEach(httpPost::setHeader);
}
CloseableHttpResponse response;
try {
response = CLIENT.execute(httpPost);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
System.out.println("response status : " + response.getStatusLine().getStatusCode());
HttpEntity responseEntity = response.getEntity();
String result;
try {
result = EntityUtils.toString(responseEntity);
System.out.println("response data : " + result);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
return SerUtil.fromJson(result, resClz);
}
public static String getAccessToken2(String url, String appId, String secret, String signKey) throws Exception {
String returnValue = "这是默认返回值,接口调用失败";
String encode = "utf-8";
Map<String, String> params = new LinkedHashMap<String, String>();
CloseableHttpClient httpClient = HttpClients.createDefault();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
//准备请求参数LinkedHashMap保持参数有序
params.put("appId", appId);
params.put("clientSecret", secret);
// 第一步创建HttpClient对象
httpClient = HttpClients.createDefault();
// 第二步创建httpPost对象
HttpPost httpPost = new HttpPost(url);
System.out.println("执行>" + url);
//对请求参数json串签名,注意json串不能被格式化美化处理如换行等不能处理后掉了原有的属性
String sig = EncryptHelper.sign(signKey, SerUtil.toJson(params));
System.out.println("参数:" + params.toString());
// 设置头信息
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");//必须是 application/x-www-form-urlencoded
httpPost.setHeader("X-Clientid", appId);//注册系统时的appId
httpPost.setHeader("X-Acloud-Data-Sign", sig);//请求json串的签名串
httpPost.setHeader("Accept", "*/*");
// 第三步给httpPost设置的参数
List<BasicNameValuePair> form = new ArrayList<BasicNameValuePair>();
for (String name : params.keySet()) {
form.add(new BasicNameValuePair(name, params.get(name)));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, encode);
httpPost.setEntity(entity);
// 第四步发送HttpPost请求获取返回值
returnValue = httpClient.execute(httpPost, responseHandler); // 调接口获取返回值时,必须用此方法
// 打出返回值
System.out.println("返回值>" + returnValue + "\n");
//fastjson处理数据
return "";
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
}