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 *

* {"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 sfr = RegistryBuilder.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 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 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 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 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 postRequestJson(String url, Object obj, Class resClz, Map 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 params = new LinkedHashMap(); CloseableHttpClient httpClient = HttpClients.createDefault(); ResponseHandler 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 form = new ArrayList(); 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 ""; } }