身份认证
1 - 单点登录
1、概述
提供标准的单点登录认证模式,有致远V8颁发临时授权码ticket,三方根据ticket获取当前登录用户信息,完成单点登录。
2、标准单点登录模式
2.1、V8标准单点登录认证(协同认证-V8)
a、说明
V8登录成功后,点击三方系统菜单前,会根据当前登录用户信息,生成临时授权码,在三方原始菜单地址后拼接参数ticket,
三方系统拦截ticket参数,根据【根据ticket获取用户信息】接口获取用户信息,模拟登陆,实现免登进入三方系统。
b、根据ticket获取用户信息接口说明
请求地址
[http://]【COP平台域名】/service/ctp-user/auth/restore
请求方式
POST
请求参数(Body)
参数名称 | 是否必填 | 参数类型 | 参数描述 |
---|---|---|---|
ticket | true | string | 用户登录后,由用户中心拼接在重定向地址最后的临时授权ticket |
请求示例
{
"ticket": "ngkhgkgd16fdg96dg1d6fg498dfg615"
}
返回参数
参数名称 | 上级节点 | 参数类型 | 参数描述 |
---|---|---|---|
status | – | int | 状态码 |
code | – | string | 响应码 |
message | – | string | 响应信息 |
data | – | object | |
content | data | object | |
code | content | string | 编号 |
orgName | content | string | 所属组织 |
tenantCode | content | string | 租户编码 |
type | content | string | 账号类型。枚举项可选值列表:NONE(空),MEMBER(内部人员),EXTERNAL_MEMBER(外部联系人) |
socialCreditCode | content | string | 统一社会信用代码 |
orgId | content | string | 所属组织ID |
phoneNumber | content | string | 手机号码 |
outsideOrgName | content | string | 外部单位名称 |
outsideOrgCode | content | string | 外部单位编码 |
orgCode | content | string | 所属组织编码 |
loginName | content | string | 用户名/登录名 |
name | content | string | 姓名 |
outsideOrgId | content | string | 外部单位ID |
allTenantUserInfo | content | array | 所有租户任职信息 |
code | allTenantUserInfo | string | 编号 |
orgName | allTenantUserInfo | string | 所属组织名称 |
tenantCode | allTenantUserInfo | string | 租户编码 |
type | allTenantUserInfo | string | 账号类型。枚举项可选值列表:NONE(空),MEMBER(内部人员),EXTERNAL_MEMBER(外部联系人) |
socialCreditCode | allTenantUserInfo | string | 统一社会信用代码 |
orgId | allTenantUserInfo | string | 所属组织ID |
phoneNumber | allTenantUserInfo | string | 手机号码 |
outsideOrgName | allTenantUserInfo | string | 外部单位名称 |
outsideOrgCode | allTenantUserInfo | string | 外部单位编码 |
orgCode | allTenantUserInfo | string | 所属组织编码 |
loginName | allTenantUserInfo | string | 用户名/登录名 |
name | allTenantUserInfo | string | 姓名 |
outsideOrgId | allTenantUserInfo | string | 外部单位ID |
返回示例
{
"status": 0,
"code": "BOOT_0000",
"message": "SUCCESS",
"data": {
"content": {
"code": "1557587001015575870039",
"orgName": "致远互联",
"tenantCode": "cop",
"type": "INTERNAL",
"socialCreditCode": null,
"orgId": "1958919590712968571",
"phoneNumber": "15575870010",
"outsideOrgName": null,
"allTenantUserInfo": [
{
"code": "1557587001015575870039",
"orgName": "致远互联",
"tenantCode": "cop",
"type": "INTERNAL",
"socialCreditCode": null,
"orgId": "1958919590712968571",
"phoneNumber": "15575870010",
"outsideOrgName": null,
"outsideOrgCode": null,
"orgCode": "group",
"loginName": "org-admin",
"name": "管理员",
"outsideOrgId": null
}
],
"outsideOrgCode": null,
"orgCode": "group",
"loginName": "org-admin",
"name": "管理员",
"outsideOrgId": null
}
}
}
2.2、三方提供临时登录授权码模式(标准认证-两次请求)
a、说明
V8登录成功后,点击三方菜单前,携带当前用户身份信息,按照三方系统要求调用三方系统接口,获取临时授权,拼接在URL后,三方拦截参数并解析后,
免登进入三方系统。
3、经典模式
说明:针对高频集成场景,平台默认提供预制的集成方式,实施人员联系三方提供必要的授权参数即可实现V8单点登录三方系统。
3.1、用友认证-YonBIP
说明:V8单点登录用友YonBIP时使用
3.2、关爱通认证
说明:V8单点登录关爱通时使用
3.3、263邮箱认证
说明:V8单点登录263邮箱时使用
3.4、阿里认证-DingTalk
说明:V8单点登录DingTalk时使用
3.5、用友认证-NC65
说明:V8单点登录NC65时使用
3.6、薪事力认证
说明:V8单点登录薪事力时使用
3.7、金蝶认证-我家云
说明:V8单点登录金蝶云时使用
3.8、协同认证-V5
说明:V8单点登录V5时使用
4、注意事项
2 - 免登
版本要求: ctp-user >= 3.2.x
1、概述
平台提供标准的免登认证机制,三方异构系统根据分配的秘钥调用接口获取免登授权码,并按要求拼接免登地址后,即可免登进入COP平台。
2、集成导图
3、集成步骤
3.1、申请APPKey和AppSecret
访问路径:管理后台—>集成平台–>开放平台–>接入应用
3.2、接口调用,获取免登授权码
调用接口【获取免登授权码】接口,接口参数规则说明:
3.3、拼接免登地址
【COP平台访问域名】:COP平台前台访问域名,例如https://saas.seeyonv8.com
【Web端待跳转地址】:免登成功后需要跳转的COP平台地址,例如首页地址:“/main/portal”
【移动端端待跳转地址】:免登成功后需要跳转的COP平台地址,例如首页地址:“/main-mobile/portal”
urlencode:编码函数,为了防止出现参数冲突,【Web端待跳转地址】和【移动端端待跳转地址】需要采用url编码后再拼接到免登地址中
【appKey】:第二步COP平台为每个应用分配的AppKey
【免登授权码】上一步接口获取的免登授权码
免登地址:【COP平台访问域名】/oauth/avoid?web=urlencode(【Web端待跳转地址】)&mobile=urlencode(【移动端端待跳转地址】)&sytype=sytoken&syid=【appKey】&sytoken=【免登授权码】
例如:
https://saas.seeyonv8.com/oauth/avoid?web=%2Fmain%2Fportal&mobile=&sytype=sytoken&syid=cd13f41d30f44d438b05b6588411178f&sytoken=SY-otokx4kfq0wtiwxm
按照以上步骤操作后,URL地址直接写入浏览器URL即可免登进入COP平台首页
3.4、验证免登授权码
注意:联调阶段或者问题定位阶段,使用【验证免登授权码】接口,验证免登授权码是否正常有效;
4、接口清单
4.1、获取免登授权码
请求地址:
【COP平台访问域名】/service/ctp-user/auth/avoid/sytoken
请求方式
POST
请求参数(Body) 参数生成示例见 5.2 java 调用示例
参数名称 | 是否必填 | 参数类型 | 参数描述 |
---|---|---|---|
responseType | TRUE | string | 请求类型, 固定值:create |
clientId | TRUE | string | 应用ID,操作步骤中的接入应用-AppKey 例如:cd13f41d30f44d438b05b6588411178f |
dataType | TRUE | string | 用户标识键,双方约定的用户标识字段,标识用于生成签名的用户标识键等于COP平台的对应字段 枚举值: loginName=用户名; mobile=手机号码; code=用户编号; email=邮箱; userid=用户ID; |
dataValue | TRUE | string | AES用户信息加密;当dataType=mobile时,用户手机号码为17300001234,则明文为17300001234 加密配置信息: 明文:17300001234 模式:CBC固定模式不可变; 填充:Pkcs7或Pkcs5固定类型不可变; 偏移量:apaasseeyonv8com 固定值不可变 密文编码:HEX类型不可变; 秘钥:接入应用分配的AppSecret,例如:93ec877511d24dda8cf86a9d7870f681 加密后结果集示例:6d52cb81d4f8ee6359b0559f3aa0bcba AES在线加密参考网站:http://tool.lvtao.net/aes |
signature | TRUE | string | 签名函数,以下四个参数经过自然排序后,拼接成一个字符串,使用SHA256加密 加密前四个参数: AppKey(接入应用分类的AppKey); AppSecret(接入应用分配的AppSecret); data(加密后的用户信息dataValue); 时间戳:请求参数中的timestamp; 如对 “abcd” 进行签名后的结果为 “88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589” SHA256在线加密参考网站:https://crypot.51strive.com/sha256.html |
timestamp | TRUE | string | 毫秒级时间戳,参与生成签名; 例如:“1720669311740” |
请求参数示例
{
"responseType": "create",
"clientId": "1242bc19f9f6493c9599ba007b9774c9",
"dataType": "mobile",
"dataValue": "6d52cb81d4f8ee6359b0559f3aa0bcba", // 对 17300001234 进行加密后的密文
"signature": "07bf5c43a0297599ea78ca72e85fea72680eb550f4a3dae4ddb4e8575950a148",
"timestamp": "1720669311740"
}
响应参数(Body)
参数名称 | 父节点 | 参数类型 | 参数描述 |
---|---|---|---|
data | SingleData | 返回值数据 | |
content | data | void | 数据对象 |
expireSeconds | content | string | 授权码有效时长,默认-1,仅可使用一次 |
sytoken | content | string | 免登授权码 |
status | int32 | 状态 | |
code | string | 错误码 | |
message | string | 返回信息 |
响应参数示例
{
"status": 0,
"code": "BOOT_0000",
"message": "SUCCESS",
"data": {
"content": {
"expireSeconds": "-1",
"sytoken": "SY-5fdin8jp0jmj8i4p"
}
}
}
4.2、验证免登授权码
请求地址:
【COP平台访问域名】/service/ctp-user/auth/avoid/sycheck
请求方式
GET
请求参数(Query)
参数名称 | 是否必填 | 参数类型 | 参数描述 |
---|---|---|---|
sytoken | TRUE | string | 免登授权码 例如:SY-o5vtq1z3bnvecwta |
syid | TRUE | string | 应用ID,操作步骤中的接入应用-AppKey 例如:cd13f41d30f44d438b05b6588411178f |
请求参数示例
【COP平台访问域名】/service/ctp-user/auth/avoid/sycheck?sytoken=SY-o5vtq1z3bnvecwta&syid=cd13f41d30f44d438b05b6588411178f
响应参数(Body)
参数名称 | 父节点 | 参数类型 | 参数描述 |
---|---|---|---|
data | SingleData | 返回值数据 | |
content | data | void | 数据对象 |
sytokenValid | content | string | 授权码是否有效 |
syidValid | content | string | syid/AppKey/ClientId是否有效 |
validity | content | string | 授权码剩余可使用次数 |
status | int32 | 状态 | |
code | string | 错误码 | |
message | string | 返回信息 |
响应参数示例
{
"status": 0,
"code": "BOOT_0000",
"message": "SUCCESS",
"data": {
"content": {
"sytokenValid": true,
"syidValid": true,
"validity": "once"
}
}
}
5、调用示例
5.1、ApiFox
注意:将一下内容导出文件名为V8开放平台.apifox.json后,使用APIFox导入即可;
{"apifoxProject":"1.0.0","$schema":{"app":"apifox","type":"project","version":"1.2.0"},"info":{"name":"V8开放平台","description":"","mockRule":{"rules":[],"enableSystemRule":true}},"apiCollection":[{"name":"根目录","id":12310375,"auth":{},"parentId":0,"serverId":"","description":"","identityPattern":{"httpApi":{"type":"methodAndPath","bodyType":"","fields":[]}},"preProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"items":[{"name":"OAuth免登","id":34341447,"auth":{},"parentId":0,"serverId":"","description":"","identityPattern":{"httpApi":{"type":"inherit","bodyType":""}},"preProcessors":[{"type":"customScript","data":"const appkey = pm.environment.get(\"app-key\");\r\nconst appsecret = pm.environment.get(\"app-secret\");\r\nconst signStr = pm.environment.get(\"signStr\");\r\nvar timestamp = new Date().getTime();\r\nconsole.log('timestamp='+timestamp);\r\nvar moment = require('moment');\r\nvar dUTC = new Date();\r\nvar formatDateTime = moment(dUTC).format('YYYY-MM-DD hh:mm:ss');\r\n\r\nvar body = pm.request.body.raw.toString();\r\nconsole.log('body='+body);\r\n\r\n//AES手机号码加密-开始\r\nvar cryptoJs = require(\"crypto-js\");\r\nconst mobile= \"17301103865\"\r\nconst key = CryptoJS.enc.Utf8.parse(appsecret);\r\nconst iv1 = cryptoJs.enc.Utf8.parse('www.seeyonv8.com');\r\nconst encrypted = cryptoJs.AES.encrypt(mobile, key, {\r\n iv: iv1,\r\n mode: cryptoJs.mode.CBC,\r\n padding: cryptoJs.pad.Pkcs7\r\n}).ciphertext.toString();\r\nconsole.log('encrypted='+encrypted);\r\n//AES手机号码加密-结束\r\n\r\n\r\n//签名计算-开始\r\nvar srcDataArr = [];\r\nsrcDataArr=[appkey, appsecret, encrypted, timestamp];\r\nconsole.log('srcDataArr='+srcDataArr);\r\nsrcDataArr.sort();\r\nconsole.log('srcDataArr='+srcDataArr);\r\nvar srcSign = srcDataArr.join(\"\");\r\nconsole.log('srcSign='+srcSign);\r\nvar signature=CryptoJS.SHA256(srcSign).toString();\r\nconsole.log('signature='+signature);\r\nvar newBody= body.replace('{{clientId}}', appkey)\r\n .replace('{{timestamp}}', timestamp)\r\n .replace('{{dataValue}}', encrypted)\r\n .replace('{{signature}}', signature);\r\n console.log('newBody='+srcSign);\r\npm.request.body.raw=newBody;\r\n//签名计算-结束\r\n\r\n","defaultEnable":true,"enable":true,"id":"VGKlxRoDhjQqm1tEhZ2V8","executionTiming":"prerequest"},{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"postProcessors":[{"id":"inheritProcessors","type":"inheritProcessors","data":{}}],"inheritPostProcessors":{},"inheritPreProcessors":{},"items":[{"name":"获取Token","api":{"id":"175366254","method":"post","path":"/service/ctp-user/auth/avoid/sytoken","parameters":{"path":[],"header":[]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"453493410","name":"成功","code":200,"contentType":"eventStream","jsonSchema":{"type":"object","properties":{}}}],"responseExamples":[],"requestBody":{"type":"application/json","parameters":[{"required":false,"description":"","type":"string","id":"OpdZpqBeRe","example":"韩","enable":true,"name":"query"}],"jsonSchema":{"type":"object","properties":{}},"example":"{\r\n \"responseType\": \"create\",\r\n \"clientId\": \"1242bc19f9f6493c9599ba007b9774c9\",\r\n \"dataType\": \"mobile\",\r\n \"dataValue\": {{dataValue}},\r\n \"signature\": {{signature}},\r\n \"timestamp\": {{timestamp}}\r\n}"},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":50,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{"disabledSystemHeaders":{}},"mockScript":{},"codeSamples":[],"commonResponseStatus":{},"responseChildren":["BLANK.453493410"],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}},{"name":"验证Token","api":{"id":"175898146","method":"post","path":"/service/ctp-user/auth/avoid/sycheck","parameters":{"query":[{"id":"B0Hw9tnMOB","name":"sytoken","example":"SY-wjls766qqv8zru67","required":false,"description":"","enable":true,"type":"string"},{"id":"ROZGpZw2Aj","name":"syid","example":"1242bc19f9f6493c9599ba007b9774c9","required":false,"description":"","enable":true,"type":"string"}]},"auth":{},"commonParameters":{"query":[],"body":[],"cookie":[],"header":[]},"responses":[{"id":"454439745","name":"成功","code":200,"contentType":"json","jsonSchema":{"type":"object","properties":{}}}],"responseExamples":[],"requestBody":{"type":"none","parameters":[],"jsonSchema":{"type":"object","properties":{}},"example":""},"description":"","tags":[],"status":"developing","serverId":"","operationId":"","sourceUrl":"","ordering":60,"cases":[],"mocks":[],"customApiFields":"{}","advancedSettings":{"disabledSystemHeaders":{}},"mockScript":{},"codeSamples":[],"commonResponseStatus":{},"responseChildren":["BLANK.454439745"],"preProcessors":[],"postProcessors":[],"inheritPostProcessors":{},"inheritPreProcessors":{}}}]}]}],"socketCollection":[],"docCollection":[],"responseCollection":[{"_databaseId":2268233,"name":"Root","type":"root","children":[],"parentId":0,"id":2268233,"items":[]}],"schemaCollection":[],"requestCollection":[{"name":"根目录","children":[],"items":[{"id":1521000,"name":"百度翻译","method":"post","path":"https://fanyi.baidu.com/langdetect","requestBody":{"type":"multipart/form-data","parameters":[{"type":"string","name":"query","sampleValue":"周","value":"周","enable":true}]},"parameters":{},"commonParameters":{"query":[],"body":[],"header":[],"cookie":[]},"preProcessors":[],"postProcessors":[],"auth":{},"advancedSettings":{},"folderId":0}]}],"environments":[],"commonScripts":[],"globalVariables":[{"id":"2272068","variables":[{"name":"url","value":"https://71d0daa2-2ac9-4a23-bc72-17c90b15a409.mock.pstmn.io","description":"","isBindInitial":true,"initialValue":"https://71d0daa2-2ac9-4a23-bc72-17c90b15a409.mock.pstmn.io","isSync":true}]}],"commonParameters":null,"projectSetting":{"id":"1776703","auth":{},"servers":[{"name":"Pre地址前缀","id":"default"}],"gateway":[],"language":"zh-CN","apiStatuses":["developing","testing","released","deprecated"],"mockSettings":{},"preProcessors":[],"postProcessors":[],"advancedSettings":{},"initialDisabledMockIds":[],"cloudMock":{"security":"free","enable":true,"tokenKey":"apifoxToken"}},"customFunctions":[],"projectAssociations":[]}
5.2、Java
package com.nowhere.demo;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
public class CipAvoidUtils {
private static final Logger log = LoggerFactory.getLogger(CipAvoidUtils.class);
private static final String AES_IV = "apaasseeyonv8com"; // 确保这是一个合适的IV字符串
private static final ConcurrentHashMap<String, AES> AESCache = new ConcurrentHashMap<>();
public static void main(String[] args) {
String clientId = "1242bc19f9f6493c9599ba007b9774c9";
String appSecret = "93ec877511d24dda8cf86a9d7870f681";
String data = "17300001234";
String timestamp = "1720669311740";
// 加密业务参数
// encryptData = 6d52cb81d4f8ee6359b0559f3aa0bcba
String encryptData = CipAvoidUtils.encrypt(data, appSecret);
System.out.println("encryptData = " + encryptData);
// 数据自然排序
// sortData = 1242bc19f9f6493c9599ba007b9774c917206693117406d52cb81d4f8ee6359b0559f3aa0bcba93ec877511d24dda8cf86a9d7870f681
String sortData = CipAvoidUtils.sort(clientId, appSecret, encryptData, timestamp);
System.out.println("sortData = " + sortData);
// sha256签名
// sign = 07bf5c43a0297599ea78ca72e85fea72680eb550f4a3dae4ddb4e8575950a148
String signature = CipAvoidUtils.sha256(sortData);
System.out.println("signature = " + signature);
}
public static String sha256(String srcData) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(srcData.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-256 algorithm not found", e);
}
}
/**
* 将入参进行自然排序
*
* @param clientId 客户端ID,对应应用的AppKey, 不能为null或空
* @param clientSecret 客户端密钥,不能为null或空
* @param data 加密后的数据,不能为null或空
* @param timestampPara 时间戳参数,不能为null或空
* @return 排序后的字符串拼接结果
*/
public static String sort(String clientId, String clientSecret, String data, String timestampPara) {
// 检查输入参数的有效性
if (StringUtils.isAnyBlank(clientId, clientSecret, data, timestampPara)) {
throw new IllegalArgumentException("All parameters must not be null or empty.");
}
String[] srcDataArr = new String[]{clientId, clientSecret, data, timestampPara};
Arrays.sort(srcDataArr);
return String.join("", srcDataArr);
}
/**
* 使用指定密钥加密字符串数据
*
* @param data 待加密的数据,不能为null或空
* @param key 加密密钥,接入应用分配的 AppSecret 的值
* @return 加密后的字符串
*/
public static String encrypt(String data, String key) {
// 检查输入数据和密钥是否有效
if (StringUtils.isAnyBlank(data, key)) {
throw new IllegalArgumentException("Data and key must not be null or empty.");
}
try {
// 根据密钥获取AES加密器实例
AES aes = getAes(key);
// 使用AES加密器加密数据并以十六进制字符串形式返回
return aes.encryptHex(data);
} catch (Exception e) {
// 记录加密失败的错误信息
log.error("Encryption failed: {}", e.getMessage(), e);
// 将加密过程中捕获的异常包装成RuntimeException重新抛出
throw new RuntimeException("Encryption failed", e);
}
}
/**
* 解密字符串
* 使用提供的密钥对加密数据进行解密
*
* @param encryptedData 加密后的数据,不能为空
* @param key 加密密钥,接入应用分配的 AppSecret 的值
* @return 解密后的字符串
*/
public static String decrypt(String encryptedData, String key) {
// 检查输入参数的有效性
if (StringUtils.isAnyBlank(encryptedData, key)) {
throw new IllegalArgumentException("Encrypted data and key must not be null or empty.");
}
try {
// 根据密钥获取AES实例
AES aes = getAes(key);
// 解密数据
return aes.decryptStr(encryptedData);
} catch (Exception e) {
// 记录解密失败的错误信息
log.error("Decryption failed: {}", e.getMessage(), e);
// 将解密过程中发生的异常包装成运行时异常重新抛出
throw new RuntimeException("Decryption failed", e);
}
}
private static AES getAes(String key) {
return AESCache.computeIfAbsent(key, k -> {
try {
return new AES(Mode.CBC, Padding.PKCS5Padding, k.getBytes(StandardCharsets.UTF_8), AES_IV.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
log.error("Failed to create AES object for key: {}", k, e);
throw new RuntimeException("Failed to create AES object", e);
}
});
}
}
6、注意事项
3 - 三方统一身份认证
1、概述
针对市场上热门的三方统一身份认证系统,平台提供了开箱即用的接入机制。
2、预制统一身份认证清单
2.1、信安
2.2、腾讯玉符
2.3、派拉
2.4、CAS
2.5、SAML2
3、集成配置步骤
3.1、使用系统管理员账号登录管理后台
3.2、进入认证服务
3.3、按需选择预制三方统一身份认证系统
3.4、按需选择客户端类型
3.5、联系三方统一身份认证系统获取授权信息
3.6、重启微服务ctp-user
3.7、前台验证
注意,在未登录情况下,浏览器地址中输入【COP平台访问域名】/main/portal时,系统系统跳转到三方统一身份认证页,属于对方账号密码后可以正常进入COP首页,标识配置正确并生效。