test

新建PPT
这里是新建的

腾讯
PCG
版权内容
RSS
接入说明

一、简介
1. 请只提供原创新闻内容
2.RSS 输出请勿包含与文章正文无关的内容,包括且不限于:广告、相关阅读、相关报道等。
二、
RSS
协议
开发规范
文章!
字段分为必填项和可选项,必填的字段必须有
。选填的字段尽量填写。!
1. 接入RSS 协议格式
<rss version="2.0">
频道名称
定义指向频道的超链接
媒体/频道介绍
生存时间
文章标题
作者名称
文章分类
最后发布时间
正文
文章地址
中经社单点登录接口文档
V1.3.1
技术与数据中心
2018年10月
118
1Oauth2认证接口
1.1流程简述
、业务系统发现用户未登录状态,需要根据应用跳转接口的要求封装并进
行页面重定向
、重定向后单点登录系统会进行响应登录工作。并根据用户接受的进
行重定向,给业务系统发送等相应信息
、获取后,通过接口调用的方式获取。
、获取后,通过接口调用的方式获取用户信息等信息。其
中用户信息是加密的,不同业务系统的秘钥是不同的,需要向管理员获取。
、需要登出的话需要通过 先调用单点登陆的,然后处理业务系统的登出
相关功能。(此登出会把整个单点登录状态的变为登出状态,其他的业务系统
也会受到影响)。
1.2前置条件
、认证需要业务系统做相应的修改工作。
、此认证方式适合于基于协议的应用。
1.3应用登录跳转
用户访问业务系统时,业务系统需要拦截用户的登陆请求,并跳转到中经
社单点登录系统中,中经社单点登录系统会向用户展示相应的登录及其他操作
218

界面。
当业务系统拦截到登陆请求后,需要根据以下要求封装,然后进行页
面重定向到此上。
的访问地址: !" #$$$%&$%'$
封装参数说明:
参数名参数值说明
response_typecode固定值 ¢code¢
scoperead,write
固定值
¢read,write¢
client_idoauth1123
客户端在UIAS上注
册时的应用代
码,UIAS提供
redirect_uri
http%3A%2F%2Fapp.xhsceis.com%2F
oauthClient
%2Fauthorization_code_callback
客户端的回调函数,
客户端自定义
state
3e04e206-ad4c-4dff-a927-
d7fab1ad24f4
一个随机值, UIAS
将原样返回,用于检
测是否为跨站请求
ÕCSR×)等,客户端自
定义,32位UUID
gotoUrl
http%3A%2F%2Fapp.xhsceis.com
%3A8080%2Fcxbook%2Fsys
%2FroleMag.jsp
应用向多因子认证前
访问的URL
referer
http%3A%2F%2Fapp.xhsceis.com
%3A8080%2Fcxbook%2Fwelcome.jsp
认证发起时的url,
可用于判定认证来源
Õ可以不写)
p01
str1
扩展参数1
p02扩展参数2
p03扩展参数3
p04扩展参数4
p05扩展参数5
p06扩展参数6
p07扩展参数7
p08扩展参数8
p09扩展参数9
P10扩展参数10
示例:
!" #$$$%&$%'$ (
)*+*,$+$$*+$$*
318

-%-.- !$ #-.'$
-.$"/+*001222032
454+&*-%-.-. !$ #-.!-.)
-.6& +3*+3*
1.4获取code接口
当业务系统完成了应用登录跳转的操作后,并跳转到单点登录系统。此时
单点登录系统会根据用户的状态进行一些列操作,包括登陆、如果是初始密码
则要强制修改密码等等。当着操作完成后,单点登录系统会进行回调业务系统,
也就是单点登录系统会进行页面重定向到业务系统的那个获取的回调
,并把信息已经之前传入的一些参数发送给这个回调。
回调参数如下:
参数名参数值说明
用来获取access_tocken的code值
'
客户端在UIAS上注册时的应用代码
&
应用登录跳转传给单点登陆的
&参数,便于业务系统重定向
p01
应用登录跳转传给单点登陆的扩展
参数
p02
应用登录跳转传给单点登陆的扩展
参数
p03
应用登录跳转传给单点登陆的扩展
参数
p04
应用登录跳转传给单点登陆的扩展
参数
p05
应用登录跳转传给单点登陆的扩展
参数
p06
应用登录跳转传给单点登陆的扩展
参数
p07
应用登录跳转传给单点登陆的扩展
参数
p08
应用登录跳转传给单点登陆的扩展
参数
p09应用登录跳转传给单点登陆的扩展
418

参数
P10
应用登录跳转传给单点登陆的扩展
参数
具体回调重定向实例如下:
!$ #'$$"/(
*%789:;+'*+&*-%-.-. !$ #
-.!-.)-.6& +3*+3*
1.5获取token
当业务系统获取完 后,就可以根据这个 获取。此
接口不用进行重定向,直接通过调用的方式即可。具体接口说明如下:
、接口:
如果业务系统部署在中经社机房内,则接口如下:
< 0 4 0303$
如果业务系统部署在互联网环境下,则接口如下:
!" #$
、请求参数
参数名参数值说明
grant_typeauthorization_code
授权类型,固定值
¢authorization_code¢
client_idOauth1123
客户端在UIAS上注册时
的应用代码,UIAS提供
client_secretOauth1123
客户端在UIAS上注册时
的应用代码,UIAS提供
code77unCQ
通过第二步,从UIAS获
取code参数值
redirect_uri
http%3A%2F%2Fapp.xhsceis.com
%2FoauthClient
%2Fauthorization_code_callbac
k
客户端的回调函数,客
户端自定义
、内网请求示例
< 0 4 0303$(
518

$$*+$*+&)*$"/+
$$*-%-.-. !$ #-.'$
-.$"/+*<<'=
、互联网请求示例
!" #$(
$$*+$*+&)*$"/+
$$*-%-.-. !$ #-.'$
-.$"/+*<<'=
、返回结果():
>???012232412
1140?,?)???,?!$$?00,???$?@
:用来获取用户信息的串
):类型,对于业务系统无实际意义
!$$:过期时间。
8:访问权限类型
1.6用户信息接口
用户信息接口主要在应用系统获取 成功后,根据 获取单点登录
系统对应用系统开放的基本信息。
、接口:
如果业务系统部署在中经社机房内,则接口如下:
< 0 4 0303$$)$5
如果业务系统部署在互联网环境下,则接口如下:
!" #$$)$5
、请求参数
参数名参数值说明
access_token
c14945e6-b4c5-40aa-8426-
63e6e8cd319b
AccessToken
618
、内网请求示例
< 0 4 0303$$)$5(*012232
4121140
、互联网请求示例
!" #$$)$5(*012232
4121140
、返回结果():
>???3333333?,?'??#?@
':应用代码
:接口返回的密文,该密文需要通过单点登录系统发放的公钥进行解密。
1、解密过程说明(具体A代码详见附件)
每4位3字符串对应位%8'BB码,解析后得到一个1字符串
使用的C1D& ## $) C1E解码,
指定字符集为F.24,得到二进制数组)
根据'提取对应的应用秘钥文本文件(B%8G)# ),读
取该文件,得到3字符串,将3串按照4位对应位%8'BB码的原
则,解析得到1字符串,对该字符串进行1解码,指定字符
集为F.24,得到二进制数组)(公钥),3 位HG'8填充模
式。
使用8%算法,使用公钥)对)进行解密,得到原文的二
进制数组)
将数组)指定字符集F.24,转为字符串,该字符串即为接口返
回的原文
示例:3串转为%8'BB码算法测试数据
3串:
33333333333333333333333333333333333333
%8'BB码:I*
示例:1串转为原文字符串算法测试数据
1串:
7;J#09;CBKC6LM".96NJ#F6MF#.3MH.CK=#$F.#J
7)46KKLO!.JF#6P=L"J=P"6N'JP=#9
字符串:
'5N3K!Q93OMA5PL38:HH$OCAI=5G
718

<FO"B4MPC=.HCAM!1LICM
1串:
8%!9MJ.!6:6FOK.JOM#P7#HF;F:LJ:MPF3JF=QF"&POM;.M
=!6KJM;6:L'KMA;PMCJ".#3G8.!.9!%**
字符串:
L37:&=Q3LP;.;QR=;B:6.PPF;41'CJ3A'3CC4!#H
70:"7&.IJB%QJ&)$Q;
1串:
M")LF37M:!M"P.NFO1M#P;MM.9LPNP9.!KJ8."#3=3;M
MAP=MM79K"BJPK6MJ;PJKC;M73Q9:*
字符串:
98JLNF6$7QF$=9"M'#:7C&=QA!L%"'L'<N)%
4OOJ1#P58OM&0.OAH'MA7%
<、解析后的用户信息()
>????,?'??$?,?#???,?P??3?,?&P#?
?技术与数据中
心?,???01<0401<003?,?&$??"&?,?&B?
?3333333331?,?#???,?#$H??413333,3,3,3333PK
333333,443<?,?&?,?F)A???,?$B??41%4.:4C.
CC40.':11C:4?,?#$??"&S!$ &?,?&'??3333333331?,
?$F$##??000<1?,?B??55?,?#??张
三?,?'??"H?,?F)???,?#???@
参数名参数值说明
B55
用户id,唯一值
&$
zhangsan
用户登陆系统的登录名(用
于it系统的唯一标识)
#
张三姓名
&B<3
机构ID
&P#
技术与数据中心机构名称
&'<
机构代码
#$H
413333,3,3,3333
PK333333,443<
多个信息集合,包括手机
号,员工编号,考勤编
号,ncid,内部电话,中间
由逗号分隔
818

#$"&S!$ &
邮箱
F)
用户登录系统使用的认证方
式ID串。认证方式ID如
下:1密码,2证书,3令牌,4
短信,5二维码。
'"H
单点登录系统唯一代码标示
'"H
应用代码
$B
41%4.:4C.CC40.':
11C:4
单点用户在B%8上的
$B,此$用来登出系
统
P
B%8的唯一节点标示
1.7单点登出
建议慎重调用这个接口,会影响已经登陆的系统
单点登录应用通过$B进行单点登出。
、接口:
!" #$$T
、请求参数
参数名参数值说明
$B
41%4.:4C.CC40.':11
C:4
$B
、调用方式()
此调用只支持前台通过的方式调用。
$.ajax({
url:"https://auth.xhszjs.com/uias/uias/shotOff?
sessionId=186A8121FE8B2F2B52B89FC2E6436BE8&jsoncallback=?",
dataType: "jsonp",
type: 'get',
success: function(data) {
if (data) {
//登出成功,并继续后续操作
} else {
//登出失败
}
},
error:function(XMLHttpRequest,textStatus,errorThrown){
918

//登出失败
}
});
1.8测试环境
建议现在测试环境上联调后,再更改配置到生产环境,测试环境不支持互
联网调试。只能通过黑楼A登入后进行调试。
测试环境
< < 10303
2Kaa消息推送(用户及机构变化)
2.1卡夫卡参数
服务地址:R !$ 030,R !$ 030,R !$ 030
F$:$2#&
2.2通用消息格式
格式形式:
参数名参数值说明
msgId
消息id
此消息的唯一id
msgType
消息类型
1、用户修改,2、用户删
除,3、机构修改,4、机构
删除,5、账号认证修改
msgContent
消息内容具体传入的参数,格式是
1018

json
2.3用户信息修改消息格式
示例:
{"msgId"="01695779878d1c0089166b7888f46500","msgType”=1,
“msgContent”={"usercode":"xxx","username":"XXX","userstatus":"0","accountstatus":"0","
mobilephone":"18601020304","phonein":"88051111","email":"xxx@xinhua.org","ncid":"00
011A100000000047Z2","timecardid":"10111","stuffcode":"41230","orgCode":"31700_09"}
}
其中msgContent具体的用户信息。
{"usercode":"xxx","username":"XXX","userstatus":"0","accountstatus":"0","mobilephone":"
18601020304","phonein":"88051111","email":"xxx@xinhua.org","ncid":"00011A10000000
0047Z2","timecardid":"10111","stuffcode":"41230","orgCode":"31700_09"}
参数说明
参数名参数值说明
usercode
用户的唯一编码
用户的登录账号,全局唯一
username
用户名称用户的姓名
userstatus
用户状态0:正常,1、异常
accountstatus
账号状态0:正常,1、异常
mobilephone
手机号手机号
emailemailemail
ncid
人员$
对接NC系统的人员信息唯一
值
timecardid
考勤$
对接考勤系统的唯一值
stuffcode
员工编号员工卡的号码
orgCode
所属机构所在机构的编码
2.4用户信息删除消息格式
示例:
{"msgId"="01695779878d1c0089166b7888f46500","msgType”=2,“msgContent”={"userco
de":"xxx"}}
其中msgContent具体的用户信息。
{"usercode":"xxx"}
1118

参数说明
参数名参数值说明
usercode
用户的唯一编码
用户的登录账号,全局唯一
2.5组织机构修改
示例:
{"msgId"="01695773beca1500b10ab70698d01ea0","msgType”=3,
“msgContent”={"orgName":"中经社控股有限公
司","orgCode":"30103_01","parentCode":"30103"}}
其中msgContent具体的机构信息。
{"orgName":"中经社控股有限公司","orgCode":"30103_01","parentCode":"30103"}
参数说明
参数名参数值说明
orgCode
机构编码
机构的编码,全局唯一
orgName
机构名称
机构的名称
parentCode
上级机构编码
上级该机构的编码
2.6组织机构删除
示例:
{"msgId"="01695773beca1500b10ab70698d01ea0","msgType”=3,
“msgContent”={"orgCode":"30103_01"}}
其中msgContent具体的机构信息。
{"orgCode":"30103_01"}
参数说明
参数名参数值说明
orgCode
机构编码
机构的编码,全局唯一
3附件1(用户结果信息编解码)
调用顺序见#$函数
import java.io.ByteArrayOutputStream;
1218

import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.util.PublicKeyFactory;
publicclass Decrypto {
private static final int MAX_DECRYPT_BLOCK = 128;
private static final String KEY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "MD5withRSA";
public static final String CHARSER = "UTF-8";
public static String appKey;
public static String parseUIAS(String cryptoText, String appCode, String
UIASFilePath, String decrypto) {
String result = "";
String pkey = "";
InputStream is = null;
try {
String fileName = UIASFilePath + "UIASKey_" + appCode + ".dat";
is = new FileInputStream(fileName);
byte[] b = newbyte[is.available()];
is.read(b);
is.close();
pkey = new String(b, "UTF-8");
pkey = b2s(pkey);
} catch (Exception e) {
e.printStackTrace();
} finally {
1318

if (is != null) {
is = null;
}
}
try {
if (!("".equals(pkey))) {
cryptoText = b2s(cryptoText);
byte[] data = decryptBASE64(cryptoText);
byte[] dedata = (byte[]) null;
if ("PKCS1".equals(decrypto))
dedata = decryptByPubKey2(data, pkey);
else {
dedata = decryptByPubKey(data, pkey);
}
if (dedata != null)
result = new String(dedata, "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static String initAppkey(InputStream appKeyIS) throws IOException{
byte[] b = new byte[appKeyIS.available()];
appKeyIS.read(b);
String keyStr = new String(b, "UTF-8");
keyStr = Decrypto.b2s(keyStr);
appKey = keyStr;
return keyStr;
}
public static String parseUIAS(String appKey,String cryptoText, String
decrypto) {
String result = "";
try {
if (!("".equals(appKey))) {
cryptoText = b2s(cryptoText);
byte[] data = decryptBASE64(cryptoText);
byte[] dedata = (byte[]) null;
if ("PKCS1".equals(decrypto))
dedata = decryptByPubKey2(data, appKey);
else {
1418

dedata = decryptByPubKey(data, appKey);
}
if (dedata != null)
result = new String(dedata, "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static boolean verifySign(byte [] data, String pKey, String sign) throws
Exception {
byte[] keyBytes = decryptBASE64(pKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(decryptBASE64(sign));
}
public static byte[] decryptByPubKey(byte[] data, String pkey) throws Exception
{
byte[] keyBytes = decryptBASE64(pkey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key pubKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(2, pubKey);
return segmentCrypt(data, cipher, MAX_DECRYPT_BLOCK);
}
public static byte[] decryptByPubKey2(byte[] text, String pkey) throws
Exception {
byte[] data = (byte[]) null;
ByteArrayOutputStream bout = new ByteArrayOutputStream(MAX_DECRYPT_BLOCK);
try {
1518
byte[] keyBytes = decryptBASE64(pkey);
AsymmetricKeyParameter akp = PublicKeyFactory.createKey(keyBytes);
RSAKeyParameters rsaAKp = (RSAKeyParameters) akp;
BigInteger modulus = rsaAKp.getModulus();
BigInteger exponent = rsaAKp.getExponent();
RSAKeyParameters pubParameters = new RSAKeyParameters(false, modulus,
exponent);
AsymmetricBlockCipher eng = new RSAEngine();
eng = new PKCS1Encoding(eng);
eng.init(false, pubParameters);
int j = 0;
int l1 = text.length;
int l2 = j * MAX_DECRYPT_BLOCK;
int l3 = l1 - l2;
while (l3 > 0){
int aaa = (l3 > MAX_DECRYPT_BLOCK) ? MAX_DECRYPT_BLOCK : l3;
byte[] d1 = eng.processBlock(text, l2, aaa);
bout.write(d1);
++j;
l2 = j * MAX_DECRYPT_BLOCK;
l3 = l1 - l2;
}
data = bout.toByteArray();
} catch (Exception e) {
throw e;
}
return data;
}
private static byte [] segmentCrypt(byte[] data, Cipher cipher, int maxBlock) {
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] cache = (byte []) null;
byte[] result = (byte[]) null;
int offSet = 0;
int pos = inputLen;
int i = 0;
try {
while (pos> 0) {
if (pos > maxBlock) {
pos = maxBlock;
1618
}
cache = cipher.doFinal(data, offSet, pos);
out.write(cache, 0, cache.length);
++i;
offSet = i * maxBlock;
pos = inputLen - offSet;
}
result = out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
cache = (byte[]) null;
out = null;
}
return result;
}
public static byte[] decryptBASE64(String key) throws Exception {
return Base64.decodeBase64(key.getBytes("UTF-8"));
}
public static String b2s(String binStr) {
String[] tempStr = StrToStrArray(binStr);
char[] tempChar = newchar[tempStr.length];
for (int i = 0; i < tempStr.length; ++i) {
tempChar[i] = BinstrToChar(tempStr[i]);
}
return String.valueOf(tempChar);
}
private static String[] StrToStrArray(String str) {
int len = str.length()/ 8;
String[] arr = new String[len];
for (int i = 0; i < len; ++i) {
arr[i] = str.substring(8 * i, 8 * (i + 1));
}
return arr;
}
private static char BinstrToChar(String binStr) {
int[] temp = BinstrToIntArray(binStr);
int sum = 0;
1718

for (int i = 0; i < temp.length; ++i) {
sum += (temp[(temp.length - 1 - i)] << i);
}
return (char) sum;
}
private static int[] BinstrToIntArray(String binStr){
char[] temp = binStr.toCharArray();
int[] result = newint[temp.length];
for (int i = 0; i < temp.length; ++i) {
result[i] = (temp[i] - '0');
}
return result;
}
}
具体调用过程:
1、首先是初始化密钥文件,把密钥文件读取到内存中来,以便重复利用。
logger.info("读取uisa key文件:");
String keyPath = "/path of key file";
File keyFile = new File(keyPath);
InputStream is = new FileInputStream(keyFile);
String keyStr = Decrypto.initAppkey(is);
is.close();
logger.info("完成uisa key文件的初始化:"+keyStr);
2、具体解密文件
String userJson = Decrypto.parseUIAS(Decrypto.appKey,result, "RSA");
日中result就是需要解密的那个一1和0组成的字符串。
1818

责任编辑:wangshujun
网友评论