sso组件

一、准备工作

1.确认动态域名

​ 请首先确认你从得助平台获取的动态域名,得助平台提供的动态域名的格式形如: xxx.51ima.com。本文档后续章节的例子中使用的动态域名为mydomain.51ima.com。

2.sso配置

1)请使用主账号登录得助后台,进入SSO配置页面,路径:设置-->系统对接-->第三方账号登录,填写相关的SSO配置。如下图:

登录URL:填写第三方平台的登录页地址;

默认部门:选择一个部门(sso登录成功后用户在得助后台的部门);

默认角色:选择一个角色(sso登录成功后用户在得助后台的角色);

退出URL:在得助后台退出后要跳转的URL;

sso**整体流程**:

用户访问得助后台域名(比如mydomain.51ima.com)

-->页面自动跳转到第三方平台“登录URL”

-->用户填写第三方平台的用户名密码进行登录

-->第三方平台后台调用sso登录接口获取authorization(在header中),返回给第三方平台前端页面

-->第三方平台前端页面使用window.location.href方式跳转到得助平台,例如:

2)填写完成并点击“保存”后,配置页面将显示由得助后台系统为你生成的鉴权token,请妥善保管该token,后续接入开发会使用该token来加密登录信息。

二、开发步骤

​ 此处假设你已经完成“准备工作”一节中所有的要求,并已准备了一个Web系统用于开发。

1.页面开发

你的Web页面需要通过调用得助平台提供的SSO登录接口,来完成SSO登录功能

以下是SSO登录接口说明:

接口地址 https://gateway-mydomain.51ima.com/basic/user/sso/login 接口地址的域名部分【mydomain】需要填写你从得助平台获取的动态域名
方法 POST
接口参数 (URL参数) data 登录数据的加密字符串【必须encode】。data参数对应的值是对一个Json字符串使用rsa算法加密后生成的字符串(该json字符串字段见下方表格)。rsa使用的加密密钥,就是准备工作一节中获取到的鉴权token,为保证鉴权token不被窃取,建议在你的web后台实现接口,完成加密过程。
接口参数 (URL参数) timestamp 当前时间戳

data参数字段如下:

字段code 是否必填 描述
thirdpartAccount 你使用的Web系统的登陆账号
email 邮箱
phone 手机号
empno 工号
timestamp 当前时间戳,必须与接口参数中的timestamp的值相同

接口调用成功后,会以json格式返回登陆信息。返回的header中含有字段名为authorization的参数。在获取到该参数后,即可通过href链接的方式直接跳转到得助平台,跳转链接需增加token参数, 值就是返回Json中authorization字段的值, 下图为跳转链接生成示例:

此时,由于之前已经通过SSO登录接口登录了得助平台,跳转完成后就会以已登录的状态进入得助平台管理界面,SSO登录成功!

注意:data和timestamp参数登录成功一次以后,就不能再使用了,后续重新登录需要使用新的timestamp和data;

2.后台接口开发

​ 鉴权token属于敏感数据,因此强烈建议你避免在前端js中使用鉴权token完成登录数据的加密,更好的方式是将鉴权token安全存储在你的web后台能访问的位置,并在你的web后台中实现一个登录数据加密接口来完成数据加密。 ​ 该接口只完成RSA加密,RSA是公开的标准加密算法,因此具体的实现由你web后台采用的技术框架而定,如在开发过程中遇到阻碍,可直接联系得助平台获取技术支持。

data参数加密demo

long timestamp = System.currentTimeMillis();
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", "xxx@xxx.com");
jsonObject.put("phone", "13800138000");
jsonObject.put("empno", "10000");
jsonObject.put("thirdpartAccount", "admin");
jsonObject.put("timestamp", timestamp);
// 页面上的token
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCatIpy6MzOKGNz0OUMEd39DS9Mx3CUaaRY+Af0o877dgYKozWidLiF4Jj+3/O4Ee9+xHKRtPQhSdKs1QBXE6YxA+ANgr0DEpdFF464PkHGS+pFinOhUqJJaPio0AdHKEadfO1YcscdcMBbITBvcZU575t6HF6h1WZr51kGDjWtQwIDAQAB";
String result = RSAUtil.rsaEncrypt(jsonObject.toString(), publicKey);
String data = URLEncoder.encode(result, "utf-8");

RSA加密类代码如下:

public class RSAUtil {
    /**
     * 密钥长度(bit)
     */
    // FIXME 按公司规范,秘钥长度需要大于2048
    public static final int KEY_LENGTH = 1024;

    public static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * <p>
     * 单次解密最大密文长度,这里仅仅指1024bit 长度密钥
     * </p>
     *
     * @see #MAX_ENCRYPT_BLOCK
     */
    public static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 加密算法
     */
    public static final String ALGORITHM_RSA = "RSA";

    /**
     * 算法/模式/填充
     */
    public static final String CIPHER_TRANSFORMATION_RSA = "RSA/ECB/PKCS1Padding";

    /**
     * 签名算法
     */
    public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

    /**
     * UTF-8字符集
     **/
    public static final String CHARSET_UTF8 = "UTF-8";

    /**
     * GBK字符集
     **/
    public static final String CHARSET_GBK = "GBK";

    public static final String CHARSET = CHARSET_UTF8;

    /**
     * 得到公钥
     *
     * @param key     密钥字符串(经过base64编码)
     * @param charset
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key, String charset)
            throws Exception {
        byte[] keyBytes = Base64.decodeBase64(key.getBytes(charset));

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 得到私钥
     *
     * @param key     密钥字符串(经过base64编码)
     * @param charset
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key, String charset)
            throws Exception {
        byte[] keyBytes;
        keyBytes = Base64.decodeBase64(key.getBytes(charset));

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 得到密钥字符串(经过base64编码)
     *
     * @return
     */
    public static String getKeyString(Key key) throws Exception {
        byte[] keyBytes = key.getEncoded();
        String s = new String(Base64.encodeBase64(keyBytes), CHARSET);
        return s;
    }

    /**
     * 公钥加密
     *
     * @param content   待加密内容
     * @param publicKey 公钥
     * @param charset   字符集,如UTF-8, GBK, GB2312
     * @return 密文内容
     * @throws Exception
     */
    public static String rsaEncrypt(String content, String publicKey,
                                    String charset) throws Exception {
        try {
            PublicKey pubKey = getPublicKey(publicKey, charset);
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] data = StringUtils.isEmpty(charset) ? content.getBytes()
                    : content.getBytes(charset);
            int inputLen = data.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = Base64.encodeBase64(out.toByteArray());
            out.close();

            return StringUtils.isEmpty(charset) ? new String(encryptedData)
                    : new String(encryptedData, charset);
        } catch (Exception e) {
            throw new Exception(
                    "error occured in rsaEncrypt: EncryptContent = " + content
                            + ",charset = " + charset, e);
        }
    }

    /**
     * 公钥加密
     *
     * @param content   待加密内容
     * @param publicKey 公钥
     * @return 密文内容
     * @throws Exception
     */
    public static String rsaEncrypt(String content, String publicKey)
            throws Exception {
        return rsaEncrypt(content, publicKey, "utf8");
    }

    /**
     * 私钥解密
     *
     * @param content    待解密内容
     * @param privateKey 私钥
     * @param charset    字符集,如UTF-8, GBK, GB2312
     * @return 明文内容
     * @throws Exception
     */
    public static String rsaDecrypt(String content, String privateKey,
                                    String charset) throws Exception {
        try {
            PrivateKey priKey = getPrivateKey(privateKey, charset);
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION_RSA);
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            byte[] encryptedData = StringUtils.isEmpty(charset) ? Base64
                    .decodeBase64(content.getBytes()) : Base64
                    .decodeBase64(content.getBytes(charset));
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet,
                            MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen
                            - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();

            return StringUtils.isEmpty(charset) ? new String(decryptedData)
                    : new String(decryptedData, charset);
        } catch (Exception e) {
            throw new Exception("error occured in rsaDecrypt: EncodeContent = "
                    + content + ",charset = " + charset, e);
        }
    }

    /**
     * 私钥解密
     *
     * @param content    待解密内容
     * @param privateKey 私钥
     * @return 明文内容
     * @throws Exception
     */
    public static String rsaDecrypt(String content, String privateKey)
            throws Exception {
        return rsaDecrypt(content, privateKey, "utf8");
    }

    /**
     * 获得密钥对
     *
     * @return
     * @throws NoSuchAlgorithmException KeyPair
     * @Title creatKeyPair
     * @Description TODO
     */
    public static KeyPair creatKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 密钥位数
        keyPairGen.initialize(KEY_LENGTH);
        // 密钥对
        KeyPair keyPair = keyPairGen.generateKeyPair();
        return keyPair;
    }
}

FAQ:

此处描述接口的常见问题。如无,则不需要此项。

results matching ""

    No results matching ""