跳到主要内容

单点登录第三方系统集成

注:版本 V7. 10.1023 以及以上版本可用

一、概念

业务系统的专业性、系统间为了降低耦合性,单系统被拆分到若干子系统。

什么是单点登录

简单来讲,如下图所示,企业用户登录到Portal门户系统,只需要登录一次,就可以访问所有相互信任的应用系统(CRM、Email、ERP等等)。

二、功能设计

流程图

三、系统集成

3.1 系统配置

登录系统进入后台,点击“系统管理”->“系统参数”->“单点登录”->“第三方系统配置”,“新增”第三方系统配置:

密钥规格

RSA2公钥私钥,长度2048bit,私钥格式:PKCS#1,公钥格式:PKCS#8。

密钥生成

RSA在线生成,访问 http://www.metools.info/code/c80.html

  • 生成密钥长度为2048,密钥格式PKCS#1,密钥密码不设置,点击“生成密钥对”。

将公钥密钥格式改为PKCS#8,访问 http://www.metools.info/code/c85.html

将以上生成的公钥整体粘贴到如下网址的输入框,选择“公钥”,格式为“PKCS1转PKCS8”,点击“转换”。

3.2 集成接口

集成功能

① 渲染单点登录的第三方系统列表;

② 向S2平台获取第三方系统RSA加密公钥,妥善保存在本地用于token加密;

③ 点击第三方子系统链接,获取该系统的单点认证路由地址;

认证路由地址:回调地址 + systemCode + token(URL编码)

http://crm.com/sso/callback?token=FED5A255A6A5BBEEC6AF3E316ED7B50FCA8F4FF5C9E287BEF145751FF5A22E1CA49F65DEE647DA404496FB8932E9A01B252F85C988B32115EFDCB56E2AE69777

使用公钥加密 token后,得到如下认证路由地址:

http://crm.com/sso/callback?systemCode=crm& token=EJyO6nlEvruA5AoS55V9B45smOZAHSIpPOx8adnl%2FA79cIi4Ty8i%2BXDh9rpGl88Z9uD16LQIxpnKxjWBJWiVbQ7bzSzxmUuAbP1ii7EYSY6OYz7qRXhIVhcD2v2F8pfzAeGWEd0fFHSBYc1E8gNeJEBULFBoSbiINIuE5ZDs2Bhl7NeFLhaSde6dsRk1O%2BIYUvf4G4xwIkWvh3cVfjmuXDAj8NmunGBxcdj4Hx9GT2pBiEJ%2FC98ytR1hOaAMB%2FyBr%2FIIgVqhpfX2uWBBpXGLSgHIT0OCSi9LAh5axigGxzJScgQOQ7q1O8E2txzH8DBTgodj9APY6IcI0zBBotMcgA%3D%3D

④ 第三方系统单点认证登录

首先使用私钥解密token,解析密文,获取认证信息。

集成接口

  • 第三方系统列表
接口名称api/System/GetThirdParties
HTTP方法GET
入参类型成员含义类型
--
出参BaseResultModelStatus0:失败;1:成功;3:异常int
Message错误提示信息String
CodeHTTPCodeString
Result第三方系统信息List<ThirdPartyInfo>
  • 获取第三方第三方系统单点认证路由链接
接口名称api/System/GetAuthCode
HTTP方法GET
入参类型成员含义类型
userCode-用户登录名String
systemCode-第三方系统编码String
出参BaseResultModelStatus0:失败;1:成功;3:异常int
Message错误提示信息String
CodeHTTPCodeString
Result单点认证路由链接String
  • 解析认证Token、获取用户信息接口
接口名称api/OrganizationExt/SSOLogin/{systemCode}
HTTP方法POST
入参类型成员含义类型
token-认证TokenString ,从body传值
systemCode-第三方系统编码String,从url传值
出参BaseResultModelStatus0:失败;1:成功;3:异常int
Message错误提示信息String
CodeHTTPCodeString
SSOLoginReponseResult: 解析结果Message:错误信息UserInfo:用户信息booleanstringUserInfo

3.3 代码 Java RSA 公钥加密代码:

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Rsa {
// RSA2 2048 PKCS8 private static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnDSqooST+PfiWyVr7454" +
"E9jAV1fHHauIP2rAf8AFMmWhZCbd3R4jpPTsEFDw7gftKHB4hijaWWOTQS8JQJe1" +
"+R/cMLUQ6rBAQWuA1iMYZLRo3N89SZyUgcTk+0sD0WxcCAC8uwJbynfgnQXZIav+" +
"/4K3SUA774Rg05Xmckt1UorF1crhHWgsIdKxuWj+oN1W1bK2na1thCA9aMTP83Y7" +
"3fiBHayrZo0YetKmGxI1sIJ/iQv/tQNAoXD7Y49yHPmv2keNf8btt75a2fvTNX0J" +
"f2oztOCkYzgmAIzKHkxe9oxUZGVzLZksojhJhr+/7mT42rUSnugwk/QmcGJhq7cm" +
"sQIDAQAB";

public static void main(String[] args) throws Exception {
String token = "FED5A255A6A5BBEEC6AF3E316ED7B50FCA8F4FF5C9E287BEF145751FF5A22E1CA49F65DEE647DA404496FB8932E9A01B252F85C988B32115EFDCB56E2AE69777";

byte[] messageEn = encrypt(token.getBytes(), publicKey);
token = new String(Base64.getEncoder().encode(messageEn));

System.out.println("加密后的字符串:" + token);
}

public static byte[] encrypt(byte[] str, String publicKey) throws Exception
{
// base64编码的公钥
byte[] decoded = Base64.getDecoder().decode(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
// RSA加密

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(str);
}
}