# 慧讯网OA登录

# 一、基本介绍

慧讯网OA登录可以在您的OA系统中实现一键登录慧讯网的功能,相比于传统登录方式更加方便快捷。登录服务是基于 HTTPS 协议的 API 接口,返回数据为 JSON 格式。使用 API 不依赖于任何语言,使用非常方便简单。通过签名的方式进行接口鉴权,保障数据安全。

# 前置条件

  1. 有自己 OA 系统的完全控制权,即有系统源代码
  2. 有自己的软件开发人员,可以修改系统代码

# 二、OA登录基本流程

uml diagram

# 三、接口文档

# 域名

# 第一步:获取token

# 接口信息

# 参数说明

参数名 类型 必填 说明
access_key_id String 秘钥ID, 由慧讯网提供
user_no String 员工编号, 由OA系统定义, 保持唯一性
time String 毫米级时间戳, 长度13位
signature String 上述参数的签名值

# 签名规则

  • 签名方法: 详见 签名方式
  • 签名源字符串顺序: access_key_id + user_no + time

# 返回结果

成功响应:

{
  "success": true,
  "token": "WmKJnpYXCOTcmwb"
}
1
2
3
4

失败响应:

{
  "success": false,
  "info": "失败原因"
}
1
2
3
4

# 第二步:使用token登录慧讯网

# 接口信息

# 参数说明

参数名 类型 必填 说明
access_key_id String 秘钥ID
user_no String 员工编号, 由OA系统定义, 保持唯一性
time String 毫米级时间戳, 长度13位
token String 第一步获取到的token
signature String 上述参数的签名值
redirect_url String 登录后重定向的地址, 不传默认跳转首页,需要进行 url encode, 避免链接格式错误

# 签名规则

  • 签名方法: 详见 签名方式
  • 签名源字符串顺序: access_key_id + user_no + time + token

# 登录URL示例

https://www.iccchina.com/users/sub_login_oa?access_key_id=qqeJcyIWVUyriCkh&user_no=001&token=WmKJnpYXCOTcmwb&time=1434692048812&signature=1P-ZmuFoOsTx_7GhukosNV1ydwg= (opens new window)

# 四、签名方式

# 说明

  1. 按照指定顺序拼接源字符串
  2. 使用 HMAC-SHA1 加密,密钥为 access_key, 由慧讯网提供
  3. 对加密结果进行 Base64 编码
  4. 对编码结果进行字符替换:
    • 去掉换行符\n
    • + (加号) 替换为 _ (下划线)
    • / (斜杠) 替换为 - (短横线)

# 代码示例

# Python 示例

import hmac
import hashlib
import base64
import time

def generate_signature(access_key, *args):
    """
    生成慧讯网API签名

    Args:
        access_key: 访问密钥
        *args: 按顺序传入的参数

    Returns:
        签名字符串
    """
    # 拼接源字符串
    source_string = ''.join(str(arg) for arg in args)

    # HMAC-SHA1加密
    signature = hmac.new(
        access_key.encode('utf-8'),
        source_string.encode('utf-8'),
        hashlib.sha1
    ).digest()

    # Base64编码
    base64_signature = base64.b64encode(signature).decode('utf-8')

    # 字符替换
    final_signature = base64_signature.replace('\n', '').replace('\r', '')
    final_signature = final_signature.replace('+', '_').replace('/', '-')

    return final_signature

# 使用示例
access_key_id = "qqeJcyIWVUyriCkh"
access_key = "jk7oxr1Iw1c0pehfU837squsvfGn3p"
user_no = "001"
current_time = str(int(time.time() * 1000))

# 获取token的签名
token_signature = generate_signature(access_key, access_key_id, user_no, current_time)
print(f"Token签名: {token_signature}")

# 假设获取到token
token = "WmKJnpYXCOTcmwb"
login_time = str(int(time.time() * 1000))

# 登录的签名
login_signature = generate_signature(access_key, access_key_id, user_no, login_time, token)
print(f"登录签名: {login_signature}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# Java 示例

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class IccChinaSignature {

    /**
     * 生成慧讯网API签名
     *
     * @param accessKey 访问密钥
     * @param args 按顺序传入的参数
     * @return 签名字符串
     */
    public static String generateSignature(String accessKey, String... args)
            throws NoSuchAlgorithmException, InvalidKeyException {

        // 拼接源字符串
        StringBuilder sourceString = new StringBuilder();
        for (String arg : args) {
            sourceString.append(arg);
        }

        // HMAC-SHA1加密
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secretKeySpec = new SecretKeySpec(
            accessKey.getBytes(), "HmacSHA1"
        );
        mac.init(secretKeySpec);
        byte[] signature = mac.doFinal(sourceString.toString().getBytes());

        // Base64编码
        String base64Signature = Base64.getEncoder().encodeToString(signature);

        // 字符替换
        String finalSignature = base64Signature
            .replaceAll("[\r\n]", "")
            .replace('+', '_')
            .replace('/', '-');

        return finalSignature;
    }

    public static void main(String[] args) {
        try {
            String accessKeyId = "qqeJcyIWVUyriCkh";
            String accessKey = "jk7oxr1Iw1c0pehfU837squsvfGn3p";
            String userNo = "001";
            String currentTime = String.valueOf(System.currentTimeMillis());

            // 获取token的签名
            String tokenSignature = generateSignature(
                accessKey, accessKeyId, userNo, currentTime
            );
            System.out.println("Token签名: " + tokenSignature);

            // 假设获取到token
            String token = "WmKJnpYXCOTcmwb";
            String loginTime = String.valueOf(System.currentTimeMillis());

            // 登录的签名
            String loginSignature = generateSignature(
                accessKey, accessKeyId, userNo, loginTime, token
            );
            System.out.println("登录签名: " + loginSignature);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

# Golang 示例

package main

import (
    "crypto/hmac"
    "crypto/sha1"
    "encoding/base64"
    "fmt"
    "strconv"
    "strings"
    "time"
)

// generateSignature 生成慧讯网API签名
func generateSignature(accessKey string, args ...string) string {
    // 拼接源字符串
    sourceString := strings.Join(args, "")

    // HMAC-SHA1加密
    mac := hmac.New(sha1.New, []byte(accessKey))
    mac.Write([]byte(sourceString))
    signature := mac.Sum(nil)

    // Base64编码
    base64Signature := base64.StdEncoding.EncodeToString(signature)

    // 字符替换
    finalSignature := strings.ReplaceAll(base64Signature, "\n", "")
    finalSignature = strings.ReplaceAll(finalSignature, "\r", "")
    finalSignature = strings.ReplaceAll(finalSignature, "+", "_")
    finalSignature = strings.ReplaceAll(finalSignature, "/", "-")

    return finalSignature
}

func main() {
    accessKeyId := "qqeJcyIWVUyriCkh"
    accessKey := "jk7oxr1Iw1c0pehfU837squsvfGn3p"
    userNo := "001"
    currentTime := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)

    // 获取token的签名
    tokenSignature := generateSignature(accessKey, accessKeyId, userNo, currentTime)
    fmt.Printf("Token签名: %s\n", tokenSignature)

    // 假设获取到token
    token := "WmKJnpYXCOTcmwb"
    loginTime := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)

    // 登录的签名
    loginSignature := generateSignature(accessKey, accessKeyId, userNo, loginTime, token)
    fmt.Printf("登录签名: %s\n", loginSignature)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 五、安全限制说明

  • 必须是从贵公司的OA系统跳转到慧讯网,慧讯网会检查HTTP请求中的 referer 参数
  • token具有时效性,建议获取后立即使用
  • 请提供服务器公网IP地址,用于设置IP白名单,否则 /api/sub_users/get_token 接口可能会调用失败
  • 请保证服务器时间准确,否则 /api/sub_users/get_token 接口可能会调用失败
  • user_no 会作为OA账号唯一标识,请保持唯一性

# 六、常见问题

  1. Q: 签名不正确怎么办?
    A: 检查参数拼接顺序、确认access_key正确、验证字符替换规则
  2. Q: token过期怎么处理?
    A: 重新调用获取token接口,获取新的token