苍穹单点登录第三方系统

栏目:云苍穹知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

苍穹单点登录第三方系统

变更记录


产品版本

更新内容更新日期
V6.0.15初始版本2024年7月





1 场景

苍穹提供OAuth协议的授权登录方式,通过OAuth2.0验证接口来获取成员的身份信息,实现苍穹单点登录第三方系统。第三方系统可以是外部的异构系统,也可以是苍穹,即苍穹A系统单点苍穹B系统


2 适用版本

金蝶云苍穹 V6.0.15及以上


3 认证流程

A) 用户访问第三方服务,第三方服务通过构造OAuth2链接(参数包括当前第三方服务的身份ID,以及重定向URI),将用户引导到认证服务器的登录页

B) 用户登录授权(已登录用户直接跳转)

C)认证服务器将用户重定向到第一步指定的重定向URI,同时附上一个授权码。

D) 第三方服务收到授权码,带上授权码来源的重定向URI,向认证服务器申请凭证。

E) 认证服务器检查授权码和重定向URI的有效性,通过后颁发AccessToken(调用凭证)

备注:D与E的调用为后台调用,不通过浏览器进行




4 操作说明

为方便理解,下文用【苍穹】和【第三方系统】进行表述“认证系统”和“被单点登录的系统”。

4.1 创建第三方应用

1)管理员登录【苍穹】系统,进入【开放服务云】-【OpenAPI】-【第三方应用】,点击【新增】按钮。

2)新增界面填写系统编码和系统名称。在【访问策略】点击【添加策略】,配置【SSO可信白名单】。

3)在【API授权】,新增获取用户信息的接口,接口编码:authen/getUserInfo


4.2 构造网页认证链接

根据业务场景构造单点登录链接或者免登链接


1)系统单点登录集成方式

用于【第三方系统】未登录时跳转至【苍穹】登录页,使用苍穹账号密码登录第三方系统。需要将构造的链接放在【第三方系统】集成代码里。

  • 链接格式:苍穹地址+app_client_id+response_code+redirect=第三方系统地址+app_client_id

    其中

    app_client_id是第三方AppID,即4.1第三方应用的系统编码。

    redirect的值“第三方系统地址+app_client_id”要进行urlcode编码。

  • 示例:https://xxx.xxxxxx:1026/login.html?app_client_id=xxxxxx&response_code=code&redirect=http%3A%2F%2F172.19.106.118%3A8080%2Fierp%2Findex.html%3FformId%3Dpc_main_console%26app_client_id%3Dthird_sys_test%26response_code%3Dcode


2)免登集成方式

用于在【苍穹】系统内点击菜单或链接免登跳转【第三方系统】。需要将构造的链接配置在【苍穹】系统内,如快速发起的外部链接上。

  • 链接格式:苍穹地址+app_client_id+response_code+redirect_uri=第三方系统地址+app_client_id

    其中

    app_client_id是第三方AppID,即4.1第三方应用的系统编码。

    redirect的值“第三方系统地址+app_client_id”要进行urlcode编码。

  • 示例:https://xxx.xxxxxx:1026/auth/authorize.do?app_client_id=xxxxxx&response_code=code&redirect_uri=http%3A%2F%2F172.19.106.118%3A8080%2Fierp%2Findex.html%3FformId%3Dpc_main_console


4.3 第三方系统集成开发

在【第三方系统】集成开发调用“获取访问accessToken”和“获取访问用户身份”接口实现用户单点登录认证。

1)获取访问accessToken

请求方式:GET(HTTPS

请求示例:http://localhost:8080/ierp/api/login.do

请求Header参数:Content-Type=application/json

请求BODY参数:

{
    "user": "17299999999",
   "appId": "third_sys_test",
   "appSecret": "123456789123456789",
    "tenantid": "",
    "accountId": "",
    "usertype": "Mobile"
}

请求结果:

{
    "data": {
        "access_token": "666522411780278272_ZOmaYoNRmT4XRl9k8RHlt1xuyxJ5fDhf0vFxNpN4EVb37eSAawuQN9RgfuO8hsSGuPHtEb849W5Y0RQxp6CR9Qcm9E4l15h6Cs2B",
        "success": true,
        "error_desc": "",
        "expire_time": 1621250199609,
        "error_code": "0"
    },
    "state": "success"
}

http请求参数说明

传入参数字段类型是否必填字段说明

user

string

用户手机号

appId

string

4.1中的第三方应用的系统编码

appSecretstring4.1中的第三方应用的AccessToken认证密钥

tenantid

string

租户ID

accountId

string

数据中心ID, 如果不输入, 默认会选取租户下的缺省数据中心

usertype

String

Mobile: 标识为手机,默认为手机
Email:标识为email
UserName:标识为用户名

language

String

语言字串: zh_CN,zh_TW等。 默认系统默认语言


2) 获取访问用户身份

该接口用于根据code获取成员信息。

请求方式:GET(HTTPS

请求示例:http://localhost:8080/ierp/kapi/v2/secm/authen/getUserInfo?code=CODE

参数说明:

传入参数字段类型是否必填字段说明
accessToken
String
调用接口凭证,请求头
code
String
通过成员授权获取到的code,每次授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

返回结果:

{
    "data":{
        "email":"ierp@kingdee.com",
        "mobile":"17299999999",
        "name":"IERP",
        "userName":"IERP"
    },
    "errorCode":"0",
    "message":null,
    "status":true
}

返回参数字段类型字段说明
errorCode
String返回码
message
String对返回码的文本描述内容
status
String返回结果
userName
String用户名
name
String姓名
mobile
String手机号
email
String邮箱


5、开发案例

以【苍穹A系统】单点登录【苍穹B系统】举例,【苍穹B系统】即为上文中的【第三方系统】

  • 第一步:在【苍穹A系统】中创建第三方应用,见上文的[4.1]章节

  • 第二步:构造网页认证链接,见上文的[4.2]章节

  • 第三步:在【苍穹B系统】开发单点登录插件并部署在B系统,见上文[4.3]章节和另一个帖子单点登录功能介绍

注意:插件是部署在B系统,即被单点的第三方系统,如果是异构系统,可能不是以插件的形式,具体以第三方系统集成方式为准。

单点登录插件示例代码:

public class DemoSSOAuth implements ThirdSSOAuthHandler {

    private static final Log logger = LogFactory.getLog(MultiTenantSSOAuth.class);

    @Override
    public void callTrdSSOLogin(HttpServletRequest servletRequest, HttpServletResponse servletResponse, String backUrl) {
        try {
            //未登录 跳转第三方登录页 地址拼接按照
            String url = 认证中心的登录地址;
            servletResponse.sendRedirect(url);
            return;
        } catch (IOException e) {
            DisCardUtil.discard();
        }
    }

    @Override
    public UserAuthResult getTrdSSOAuth(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
        UserAuthResult userAuthResult = new UserAuthResult();
        userAuthResult.setSucess(false);
        try {
            //ssoAuthConfig.getUrl()是认证中心的访问地址 示例 https://feature.kingdee.com:1026/feature_sit
            //1、调用认证中心接口 获取accessToken
            String token = "";
            String resp = HttpClientUtils.postAppJson(ssoAuthConfig.getUrl() + "/api/login.do", headerParam, body, 5 * 1000, 6 * 1000);
            if (StringUtils.isNotEmpty(resp)) {
                Map<String, Object> result = JSONUtils.cast(resp, HashMap.class, true);
                if (result.get("data") != null) {
                    Map<String, Object> tokenData = (Map<String, Object>) result.get("data");
                    token = tokenData.get("access_token").toString();
                }
            }
            //2、获取用户信息
            String code = servletRequest.getParameter("code");
            resp = HttpClientUtils.get(ssoAuthConfig.getUrl() + "/kapi/v2/secm/authen/getUserInfo?code=" + code + "&access_token=" + token + "&accountId=" + thirdAccountId);
            if (StringUtils.isNotEmpty(resp)) {
                Map<String, Object> result = JSONUtils.cast(resp, HashMap.class, true);
                if (result.get("data") != null) {
                    Map<String, Object> data = (Map<String, Object>) result.get("data");
                    userAuthResult = handleUserAuthResult(userAuthResult, data, ssoAuthConfig);
                    if (userAuthResult.getUser() == null || StringUtils.isBlank(userAuthResult.getUser().toString())) {
                        userAuthResult.setSucess(false);
                        return userAuthResult;
                    }
                    userAuthResult.setSucess(true);
                }
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return userAuthResult;
    }

    /**
     * @param userAuthResult
     * @param data
     * @param ssoAuthConfig
     * @return
     */
    private UserAuthResult handleUserAuthResult(UserAuthResult userAuthResult, Map<String, Object> data, SSOAuthConfig ssoAuthConfig) {
        if (StringUtils.isBlank(ssoAuthConfig.getUserFlag())) {
            return userAuthResult;
        }
        //1 mobile 2email 0 userName 3workNumber
        switch (ssoAuthConfig.getUserFlag()) {
            case "0":
                userAuthResult.setUserType(UserProperType.UserName);
                userAuthResult.setUser(data.get("userName"));
                break;
            case "1":
                userAuthResult.setUserType(UserProperType.Mobile);
                userAuthResult.setUser(data.get("mobile"));
                break;
            case "2":
                userAuthResult.setUserType(UserProperType.Email);
                userAuthResult.setUser(data.get("email"));
                break;
            case "3":
                userAuthResult.setUserType(UserProperType.WorkerNumber);
                userAuthResult.setUser(data.get("workNumber"));
                break;
        }
        return userAuthResult;
    }
}


苍穹单点登录第三方系统

变更记录产品版本更新内容更新日期V6.0.15初始版本2024年7月1 场景苍穹提供OAuth协议的授权登录方式,通过OAuth2.0验证接口来获取成员的身...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息