技术文章

当前位置:首页>帮助手册>技术文章

通过服务来调用接口实现单点登录

时间:2024-02-28   

本文介绍O2OA服务管理中,接口的权限设定和调用方式。

适用版本:5.4及以上版本

创建接口

具有服务管理设计权限的用户(具有ServiceManager角色或Manager角色)打开“服务管理平台”,进入接口配置视图,点击左上角的新建按钮,可创建一个新的接口。

新建接口后,在右侧属性栏中有两个配置和调用权限有关,一个是“允许访问的地址表达式”,一个收是“启用鉴权”。

image (96).png


允许访问的地址表达式

此处允许输入一个正则表达式,用来匹配调用接口的客户端的Remote_Addr,只有匹配通过,接口才允许执行。例如只允许172.16.1.50到172.16.1.56地址调用接口,可以在此处输入:

172.16.1.5[0-6]

启用鉴权

此处选择“是”的话,就需要在调用接口时传入client名称和一个加密后的token。所以我们先需要一组鉴权配置。

具有管理员权限的用户(具有Manager角色),打开“系统设置”-“系统SSO配置”,找到“鉴权配置”。

image (97).png



点击“添加鉴权配置”:

image (98).png


此处需要配置一个名称和密钥。

名称:可随意填写,就是我们在调用接口或进行SSO时要传入的client参数。

密钥:可随意填写,用于后续加密,最少8位。

此处我们假设名称填写:oa;密钥填写:platform

填写完成后确定。


image (99).png


然后我们就可以使用此鉴权配置来调用接口了。


当启用鉴权后的接口调用地址为:

http://develop.o2oa.net:20030/x_program_center/jaxrs/invoke/{name}/client/{client}/token/{token}/execute

请求方法为:POST


地址中的{name}为接口的名称或别名;

地址中的{client}为鉴权的名称;

地址中的{token}为:用户名#1970年毫秒数 使用鉴权密钥经过DES加密后的值。

javascript加密代码样例

我们使用CryptoJS进行DES加密。(GitHub: https://github.com/brix/crypto-js

function crypDES (value, key) {
    var keyHex = CryptoJS.enc.Utf8.parse(key);
    var xtoken = CryptoJS.DES.encrypt(value, keyHex, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    });
    var str = xtoken.ciphertext.toString(CryptoJS.enc.Base64);
    str = str.replace(/=/g, "");
    str = str.replace(/+/g, "-");
    str = str.replace(///g, "_");
    return str;
},

IOS加密代码样例

/// o2oa DES加密 @param publicKey 加密公钥
func o2DESEncode(code: String, publicKey: String) -> String? {
    if let encode = desEncrypt(code: code, key: publicKey, iv: "12345678", options: (kCCOptionECBMode + kCCOptionPKCS7Padding)) {
        let first = encode.replacingOccurrences(of: "+", with: "-")
        let second = first.replacingOccurrences(of: "/", with: "_")
        let token = second.replacingOccurrences(of: "=", with: "")
        return token
    }else {
        print("加密错误")
        return nil
    }
}
/// DES 加密
func desEncrypt(code: String, key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
    if let keyData = key.data(using: String.Encoding.utf8),
        let data = code.data(using: String.Encoding.utf8),
        let cryptData    = NSMutableData(length: Int((data.count)) + kCCBlockSizeDES) {

        let keyLength              = size_t(kCCKeySizeDES)
        let operation: CCOperation = UInt32(kCCEncrypt)
        let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmDES)
        let options:   CCOptions   = UInt32(options)

        var numBytesEncrypted :size_t = 0

        let cryptStatus = CCCrypt(operation,
                                  algoritm,
                                  options,
                                  (keyData as NSData).bytes, keyLength,
                                  iv,
                                  (data as NSData).bytes, data.count,
                                  cryptData.mutableBytes, cryptData.length,
                                  &numBytesEncrypted)

        if UInt32(cryptStatus) == UInt32(kCCSuccess) {
            cryptData.length = Int(numBytesEncrypted)
            let base64cryptString = cryptData.base64EncodedString()
            return base64cryptString
        }
        else {
            return nil
        }
    }
    return nil
}


Android加密代码样例

fun o2DESEncode(code: String, publicKey: String): String {
    val sutil = CryptDES.getInstance(publicKey)
    var encode = ""
    try {
        encode = sutil.encryptBase64(code)
        Log.d(LOG_TAG,"加密后code:$encode")
        encode = encode.replace("+", "-")
        encode = encode.replace("/", "_")
        encode = encode.replace("=", "")
        Log.d(LOG_TAG,"替换特殊字符后的code:$encode")
    }catch (e: Exception) {
        Log.e(LOG_TAG,"加密失败", e)
    }
    return encode
}

public class CryptDES {
    private Cipher encryptCipher = null;
    private Cipher decryptCipher = null;
    private static CryptDES des = null;
    public static CryptDES getInstance(String des_key) {
        try {
            DESKeySpec key = new DESKeySpec(des_key.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            des = new CryptDES(keyFactory.generateSecret(key));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return des;
    }
    private CryptDES(SecretKey key) throws Exception {
        encryptCipher = Cipher.getInstance("DES");
        decryptCipher = Cipher.getInstance("DES");
        encryptCipher.init(Cipher.ENCRYPT_MODE, key);
        decryptCipher.init(Cipher.DECRYPT_MODE, key);
    }    
    public String encryptBase64 (String unencryptedString) throws Exception {
        // Encode the string into bytes using utf-8
        byte[] unencryptedByteArray = unencryptedString.getBytes("UTF8");
        // Encrypt
        byte[] encryptedBytes = encryptCipher.doFinal(unencryptedByteArray);
        // Encode bytes to base64 to get a string
        byte [] encodedBytes = Base64.encode(encryptedBytes, Base64.DEFAULT);
        return new String(encodedBytes);
    }
    public String decryptBase64 (String encryptedString) throws Exception {
        // Encode bytes to base64 to get a string
        byte [] decodedBytes = Base64.encode(encryptedString.getBytes(), Base64.DEFAULT);
        // Decrypt
        byte[] unencryptedByteArray = decryptCipher.doFinal(decodedBytes);
        // Decode using utf-8
        return new String(unencryptedByteArray, "UTF8");
    }  
}





上一篇:介绍如何通过OAuth2与O2OA进行单点登录

下一篇:平台部署之OnlyOffice集成版(O2OA容器化部署)