跳到主要内容

自定义接口配置V1

此版本接口原配置可继续使用,新建请使用V2版本。

分为配置开发两步,需要按照BDP的要求开发或修改IDP的两个接口,用于和BDP完成单点登录操作。

1 接口配置

整体配置信息与SAML2.0相似,不同的是需要先完成配置才能获取加密证书(pub_key),将证书应用到接口中才能完成配置。

1.1 IDP信息

自定义配置只需要提供统一登录和登出两个接口,接口需要按照 2 接口开发 的要求接收参数和返回结果值。

如果暂无接口,如需要重新开发接口,请先任意填写两个接口,完成配置才能获取到加密证书。

1.2 匹配用户信息

登录BDP需要使用BDP的用户信息,因此须将IDP中的用户信息与BDP中进行匹配,目前支持匹配BDP的登录账户名。

  • 登录账户:IDP返回的用户信息中与BDP登录账户一致的字段,该字段应为用户的唯一标识,不能重复,如下图将IDP的“username”字段和BDP的登录账号匹配。

1.3 登出设置

开启后,退出BDP时会同时会请求IDP配置中填写的你的SSO服务登出接口,申请在IDP中退出账号信息,保持BDP与IDP两端的账号状态一致性。

不开启时,IDP配置中的登出接口无效,可随意填写。

1.4 加密方式

支持两种算法RSA与自定义,RSA主要用于Python语言,自定义适用于所有支持MD5的语言,具有更好的通用性。加密使用方式见下方代码示例。

1.5 SP信息

用于自定义IDP接口与BDP通信,均由BDP提供,请将以下信息复制粘贴至IDP服务器的配置中或在外部系统中调用:

配置项必要/可选说明
audience必要SP的标识信息
sso必要BDP的单点登录入口,用于客户通过该接口免密登录,建议作为内部门户的登录链接
acs必要BDP的登录断言的接收服务,用于接收IDP认证后返回的用户信息
slo可选BDP的单点登出服务,IDP处用户退出时,可调用该接口通知BDP退出登录状态,保持状态一致
sls可选BDP的退出接口,区别与slo仅退出BDP,调用sls时将先退出IDP后再退出BDP
pub_key必要用户信息的加密证书。保存后再次进入编辑时可见,首次进入时没有。

1.6 登录验证

完成上述配置后,点击“保存”,此时设置还未完成,仅为保存设置,需要拿到认证证书并应用到自定义IDP接口中后生效。此时保存弹窗的验证链接无效。

获取认证证书并应用后再次保存,完成配置,须通过下方验证链接确认配置有效性;验证链接为上述步骤3中的SSO地址,点击链接或新建浏览器标签页复制链接,如果配置生效页面会向IDP进行验证,未登录时进入IDP的登录页,而不是BDP的登录页;登录后应跳转进入BDP。

获取验证链接:

  • 保存时,会提示出验证链接,点击链接使用
  • 保存后,可在添加列表的“操作”中点击的“验证”

2 接口开发

开发至少一个IDP登录验证(idp_login)接口,用于校验用户在IDP(通常为企业内部账号中心)的登录状态,并返回用户信息给BDP。

2.1 接口流程

登录:

  1. 用户通过内部系统访问BDP,调用BDP提供的SSO接口,传入domain;
  2. SSO接口回调(302重定向跳转)用户系统的idp_login接口,请求校验当前用户的登录状态;
  3. idp_login接口验证用户登录状态,验证通过后回调(302重定向跳转)BDP的acs接口,传入domain和user_info(user_info字符串加密处理)信息;
  4. BDP通过acs接口读取user_info(解密),映射到BDP的用户并登入系统;

退出(仅私有云):

  1. 用户在BDP退出时,调用BDP的slo接口;
  2. slo回调用用户系统的idp_logout接口;
  3. idp_logout接口退出成功后,回调BDP的sls接口;
  4. sls接口完成退出BDP;

2.2 登录验证接口

用于接收SP(BDP)的身份验证请求,验证当前用户是否在IDP中登录并返回用户信息返回给BDP,其中user_info需要对称加密。

IDP中判断登录结果:

  • 未登录:跳转至IDP的登录页。
  • 已登录:调用IDP的ACS接口,包含将两个请求参数。

请求参数说明:

参数名称参数类型是否必填默认值参数描述最大长度
domainstring必填BDP企业域
RelayStatestring可选验证后跳转链接由BDP提供

用户信息加密:

  1. 用户信息中须包含此前在开发者中心设置的登录账户对应字段,如使用username与BDP的登录名绑定时,用户信息中携带username参数
  2. user_info = json.dumps(user_info) 将字段转成字符串
  3. 利用在BDP配置custom_sso生成的公钥,将字符串user_info 加密,rsa.decrypt(user_info, pub_key)
  4. 加密后的字符串转Base64或MD5编码
  5. Base64编码或MD5转UrlEncode编码后传参
  6. 下附Python与Java的代码示例

Python——RSA的Base64加密接口示例:

import rsa
import json
import base64
from urllib import urlencode

pub_str = '''-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAIv7BNJT2ET7TVB1iYrxm4AdCf7xXoixFq38MdlL/W4l3Z5E+6Slo3Wu
9tXv9jQtfr0aHLTzMD3oxuBKKJ20IGx4KzdvlVZfkrutyc2pOen9L5CrnKXLbSdr
j7cGcZx2FBeBI9OvFmBBwig+NTgR/ybyMh5fwrnhENHwXPIOb62NAgMBAAE=
-----END RSA PUBLIC KEY-----
'''
user_info = {"username": "admin"}
user_info_str = json.dumps(user_info)
pub_key = rsa.PublicKey.load_pkcs1(pub_str)
cry = base64.encodestring(rsa.encrypt(user_info_str,pub_key ))
print cry
payload = urlencode({"user_info": cry})
print payload

Python——自定义加密(MD5)接口示例:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import md5
from urllib import urlencode
import json

def get_token(username, pub_key):
m1 = md5.new()
m1.update(username + pub_key.replace("\n", ""))
return m1.hexdigest()

pub_key = '''-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAMr0CpVULys1pMkugjXvCSsSsX0CvpGxVQVgB/JFuOUHTTHErzOVbw8H
09e0l/IIG4jz2A1UydC4wXZCsLK6Wg5UdlfbBMhavmvHTwqsXSWxvAl5pi0r52G3
sBYGQ4q4Uo/cZC2BAl22fSaY1nKVxGaQLOinRaR34HDXM967hWNlAgMBAAE=
-----END RSA PUBLIC KEY-----
'''
user_info = {"username": "BDP_USER"}
token = get_token(user_info['username'], pub_key)
payload = urlencode({"user_info": json.dumps(user_info), "token": token, "domain": "domain"})
print payload

Java——自定义加密(MD5)接口示例:

package com.haizhi.script;

import org.json.JSONStringer;

import java.security.*;
import java.io.*;
import java.util.*;
import java.net.*;

public class UrlParse {

private String pub_key = "-----BEGIN RSA PUBLIC KEY-----\n" +
"MIGJAoGBAMr0CpVULys1pMkugjXvCSsSsX0CvpGxVQVgB/JFuOUHTTHErzOVbw8H\n" +
"09e0l/IIG4jz2A1UydC4wXZCsLK6Wg5UdlfbBMhavmvHTwqsXSWxvAl5pi0r52G3\n" +
"sBYGQ4q4Uo/cZC2BAl22fSaY1nKVxGaQLOinRaR34HDXM967hWNlAgMBAAE=\n" +
"-----END RSA PUBLIC KEY-----";

private String username = "test";
private String domain = "test";

public static void main(String args[]) {
UrlParse t = new UrlParse();
System.out.println(t.getUrlParse());
}

public String getUrlParse(){
Map<String, String> params = new HashMap<String, String>();
String user_info = getUserInfo(username);
String info = username + pub_key.replace("\n", "");
String token = UrlParse.getMD5(info);
params.put("user_info", user_info);
params.put("token", token);
params.put("domain", domain);
System.out.println(params.toString());
return UrlParse.createLinkString(params, true);
}

private static String createLinkString(Map<String, String> params, boolean encode) {
List<String> keys = new ArrayList<String>(params.keySet());
StringBuilder prestrSB = new StringBuilder();
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (encode) {
try {
value = URLEncoder.encode(value, "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
if (i == keys.size() - 1) {
prestrSB.append(key).append("=").append(value);
} else {
prestrSB.append(key).append("=").append(value).append("&");
}
}
return prestrSB.toString();
}

private String getUserInfo(String username){
JSONStringer user_info = new JSONStringer();
user_info.object();
user_info.key("username");
user_info.value(username);
user_info.endObject();
return user_info.toString();
}

private static String getMD5(String info) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(info.getBytes("UTF-8"));
byte[] md5Array = md5.digest();
return bytesToHex1(md5Array);
} catch (NoSuchAlgorithmException e) {
return "";
} catch (UnsupportedEncodingException e) {
return "";
}
}

private static String bytesToHex1(byte[] md5Array) {
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < md5Array.length; i++) {
int temp = 0xff & md5Array[i];
String hexString = Integer.toHexString(temp);
if (hexString.length() == 1) {
strBuilder.append("0").append(hexString);
} else {
strBuilder.append(hexString);
}
}
return strBuilder.toString();
}

}

2.3 单点登出接口

可选,仅用于私有化,在IDP退出时同时注销BDP的登录状态:

  1. 首先退出IDP登录状态
  2. 同时调用BDP的sls接口
  3. BDP注销登录状态

请求参数说明:

参数名称参数类型是否必填默认值参数描述最大长度
domainstring必填BDP企业域