Loading... ## 一、ECOLOGY系统配置 ### 1、配置接口白名单 在ecology系统代码目录中找到以下配置文件:`ecology/WEB-INF/prop/weaver_session_filter.properties` ``` checkurl=/api/hrm/emmanager;/api/userPhrase; uncheckurl=/api/ec/dev/app/getCheckSystemInfo;/api/ec/dev/app/emjoin; unchecksessionurl=/api/ec/dev/util/accesspage;.../api/loginportal/element/;/api/edc/fillin/; ``` 在`unchecksessionurl=`后面添加`/api/ec/dev/auth/regist;/api/ec/dev/auth/applytoken;` ### 2、发放许可证(appid) 在ecology系统数据库执行以下脚本示例( *请不要直接使用示例中的数据* ): ``` INSERT INTO ECOLOGY_BIZ_EC(ID,APPID,NAME) VALUES('123456','EEAA5436-7577-4BE0-8C6C-89E9D88805EA','上海泛微网络科技股份有限公司'); COMMIT; ``` 字段描述: * ID:数据库主键。保证与其它系统发放的许可证在数据库中的主键标识不冲突即可(`对应示例:123456`) * APPID:许可证号码。最终发放给异构系统的许可证号码,多个许可证号码保证唯一(`对应示例:EEAA5436-7577-4BE0-8C6C-89E9D88805EA`)。可访问 [http://www.uuid.online/](http://www.uuid.online/) UUID在线生成器(保证唯一即可) * NAME:许可证名称。用于快速辨识许可证发放系统(`对应示例:上海泛微网络科技股份有限公司`) ### 3、清除OAsql缓存 chrome浏览器访问 OA地址/commcache/cacheMonitor.jsp界面,点击重启加载配置。这样数据库操作修改的数据可以及时生效。 ### 4、限制许可证使用ip地址 在ecology系统代码目录中找到以下配置文件:`ecology/WEB-INF/prop/weaver_rest_token.properties` ``` # 限制Rest API Token Invoke注册端IP地址,多个IP地址之间用逗号分隔 # 例如:allowIp=127.0.0.1,192.168.0.1,172.10.0.1,10.10.10.01 allowIp= ``` 在`allowIp=`后面添加客户调用方服务器实际的ip地址( *不设置将代表不限制任何ip,生产环境建议设置* ) ## 二、异构系统编码实现认证 ### 1、引入RSA加密算法工具jar包到异构系统 * java开发语言的客户可以直接在ecology系统代码目录中找到`ecology/WEB-INF/lib/hutool-all-5.3.0.jar`文件引入到异构系统项目资源目录下。 c#参考:[RSAConvert.cs](https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/e972d0db7e50d841146010ae0e86dda9 "[RSAConvert.cs") python参考:[auth_token.py](https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/7cc1b37f6b945a7830acaee0d5b7082c "[auth_token.py") * 其它开发语言的异构系统请自行查询一下底层库实现的rsa算法。 在线测试rsa算法加解密网站:[在线RSA测试](https://the-x.cn/Cryptography/Rsa.aspx "在线RSA测试") 关于RSA算法请参考百度百科:[RSA算法](https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95/263310?fromtitle=RSA&fromid=210678&fr=aladdin "RSA算法") ### 2、JAVA演示代码([下载演示代码](https://xug.cc/usr/uploads/2022/12/4031870376.zip "[演示代码.zip")) #### 2.1 普通接口演示代码 ``` package weaver.demo; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONUtil; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Token认证测试 * * 认证过程主要采用RSA非对称加密算法 * * @author tzf 2020/6/9 */ public class MainTest { /** * 模拟缓存服务 */ private static final Map<String,String> SYSTEM_CACHE = new HashMap <>(); /** * ecology系统发放的授权许可证(appid) */ private static final String APPID = "62acf88c-55d0-465c-b08d-99cd36271231"; public static void main(String[] args) { testRestful("http://10.10.10.40","/api/system/appmanage/route",null); } /** * 第一步: * * 调用ecology注册接口,根据appid进行注册,将返回服务端公钥和Secret信息 */ public static Map<String,Object> testRegist(String address){ //获取当前系统RSA加密的公钥 RSA rsa = new RSA(); String publicKey = rsa.getPublicKeyBase64(); String privateKey = rsa.getPrivateKeyBase64(); // 客户端RSA私钥 SYSTEM_CACHE.put("LOCAL_PRIVATE_KEY",privateKey); // 客户端RSA公钥 SYSTEM_CACHE.put("LOCAL_PUBLIC_KEY",publicKey); //调用ECOLOGY系统接口进行注册 String data = HttpRequest.post(address + "/api/ec/dev/auth/regist") .header("appid",APPID) .header("cpk",publicKey) .timeout(2000) .execute().body(); // 打印ECOLOGY响应信息 System.out.println("testRegist():"+data); Map<String,Object> datas = JSONUtil.parseObj(data); //ECOLOGY返回的系统公钥 SYSTEM_CACHE.put("SERVER_PUBLIC_KEY",StrUtil.nullToEmpty((String)datas.get("spk"))); //ECOLOGY返回的系统密钥 SYSTEM_CACHE.put("SERVER_SECRET",StrUtil.nullToEmpty((String)datas.get("secrit"))); return datas; } /** * 第二步: * * 通过第一步中注册系统返回信息进行获取token信息 */ public static Map<String,Object> testGetoken(String address){ // 从系统缓存或者数据库中获取ECOLOGY系统公钥和Secret信息 String secret = SYSTEM_CACHE.get("SERVER_SECRET"); String spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY"); // 如果为空,说明还未进行注册,调用注册接口进行注册认证与数据更新 if (Objects.isNull(secret)||Objects.isNull(spk)){ testRegist(address); // 重新获取最新ECOLOGY系统公钥和Secret信息 secret = SYSTEM_CACHE.get("SERVER_SECRET"); spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY"); } // 公钥加密,所以RSA对象私钥为null RSA rsa = new RSA(null,spk); //对秘钥进行加密传输,防止篡改数据 String encryptSecret = rsa.encryptBase64(secret,CharsetUtil.CHARSET_UTF_8,KeyType.PublicKey); //调用ECOLOGY系统接口进行注册 String data = HttpRequest.post(address+ "/api/ec/dev/auth/applytoken") .header("appid",APPID) .header("secret",encryptSecret) .header("time","3600") .execute().body(); System.out.println("testGetoken():"+data); Map<String,Object> datas = JSONUtil.parseObj(data); //ECOLOGY返回的token // TODO 为Token缓存设置过期时间 SYSTEM_CACHE.put("SERVER_TOKEN",StrUtil.nullToEmpty((String)datas.get("token"))); return datas; } /** * 第三步: * * 调用ecology系统的rest接口,请求头部带上token和用户标识认证信息 * * @param address ecology系统地址 * @param api rest api 接口地址(该测试代码仅支持GET请求) * @param jsonParams 请求参数json串 * * 注意:ECOLOGY系统所有POST接口调用请求头请设置 "Content-Type","application/x-www-form-urlencoded; charset=utf-8" */ public static String testRestful(String address,String api,String jsonParams){ //ECOLOGY返回的token String token= SYSTEM_CACHE.get("SERVER_TOKEN"); if (StrUtil.isEmpty(token)){ token = (String) testGetoken(address).get("token"); } String spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY"); //封装请求头参数 RSA rsa = new RSA(null,spk); //对用户信息进行加密传输,暂仅支持传输OA用户ID String encryptUserid = rsa.encryptBase64("1",CharsetUtil.CHARSET_UTF_8,KeyType.PublicKey); //调用ECOLOGY系统接口 String data = HttpRequest.get(address + api) .header("appid",APPID) .header("token",token) .header("userid",encryptUserid) .body(jsonParams) .execute().body(); System.out.println("testRestful():"+data); return data; } } ``` 打印结果: ``` testRegist():{"msg":"ok","code":0,"msgShowType":"none","secrit":"c8b987ff-ce36-4fbe-bac5-98370b1d5c5a","secret":"c8b987ff-ce36-4fbe-bac5-98370b1d5c5a","status":true,"spk":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAbZETaIipqH7puERgJ6VVkBGKOCK+JOfr7+A+VfobRLGeXVkuCRzFj0RhlqlODzCjEff6rm0WDrcfAM6BxfjCciCKx2EXqjklfgZyY/gGf8PYfVmPG55k37edba4MpG+R1fcMtsB5qRHTpEVfoVBlr8ys1VhA/7dv+JLwg5B+FQIDAQAB"} testGetoken():{"msg":"获取成功!","code":0,"msgShowType":"none","status":true,"token":"7099a965-7ef4-4e2d-a1e2-a4d66a10e945"} testRestful():{"schema":"http","code":0,"port":80,"msgShowType":"none","ip":"10.10.10.40","host":"192.168.42.163","type":"1","url":"/spa/coms/static4mobile/index.html#/menu-preview?id=appPage_ooxtkh&checkAccess=1","status":true} ``` #### 2.2 “非用户” 接口调用(KB190901版本及以上) > “非用户” 接口是指系统存在某些未直接配置接口白名单,且接口内部无需校验用户的普通REST接口,此时无需userid的参数。例如:获取系统信息,上传文件,同步数据,调整配置,检查状态等等接口。如果不确定,请联系相关接口提供方确认接口是否登录后访问,是否强校验用户权限。 ``` public static void testRestful() throws Exception{ //httpclient的使用请自己封装,可参考ECOLOGY中HttpManager类 HttpManager http=new HttpManager(); //请求头信息封装集合 Map<String, String> heads=new HashMap<String, String>(); //接口参数信息封装集合 Map<String, Object> param=new HashMap<String, Object>(); //封装参数到请求头 heads.put("token", "申请token接口成功时返回token值"); heads.put("appid", "5583bc0e-220e-4a44-8e14-d838d47ad9b7"); //该参数于190901版本增加 heads.put("skipsession", "1"); //...... //封装接口请求参数 //...... //调用接口相关系统接口 String data=http.postDataSSL("http://127.0.0.1:9990/api/非用户接口地址", param,heads); //返回接口响应参数 System.out.println(data); /**********************其它业务逻辑实现***********************/ } ``` ## 三、API文档在线说明 **1、简要描述:向OA系统发送许可证信息进行注册认证** * 许可证注册接口(请求一次即可,后面每次请求都是更新) **请求URL:** * `http://xx.com/api/ec/dev/auth/regist` **请求方式:** * POST **请求头部参数:** | 参数名 | 必选 | 类型 | 说明 | | --------- | ------ | -------- | ---------------------------------------------- | | appid | 是 | string | 许可证号码 | | loginid | 是 | string | OA系统账号登录名(KB1906版本及以上已废除) | | pwd | 是 | string | 账号密码加密后的密文(KB1906版本及以上已废除) | | cpk | 是 | string | 异构系统公钥 | **接口参数:无** **返回示例** ``` { "msg": "ok", "errcode": "0", "code": 0, "msgShowType": "none", "secrit": "e0ab4a73-e9c6-4ae5-9dac-f21a7807991a", "errmsg": "ok", "status": true, "spk": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNIfHNjAvtvkSKtAj79mkHOk5/bDwrGVykRJ7saI1oLHPp8lEQjBP5Ae4Te5chzflLLEj4WP24JnY2ahzb8xnPU/HNt/lwhykjoxVPoczdlXL4jcdMuvgitgCQdrqPgtpzrKNOoKbTz9vagMl0LbzGlSzGPF4PAlGDw+OrgOMsiWXyG1EsQWOW5zfwnnGfvnPZlpSKfDKT3m+9oPL/cWQv6FU1A1kHO4ADT+Np8Q2n33mMJC1Sc+YiFjNIblGoB0AME7M0hb+Ln4b+n+23jsBBeZhfBdmRdLY31AALWIuJH1+8KZvaaMS0OwkBdCfZhF4chWYSRAV4yjCx19Ax/wBQIDAQAB" } ``` **返回参数说明** | 参数名 | 类型 | 说明 | | ------------- | --------- | ------------------------------------------------------------------------------- | | status | boolean | 响应状态。true:成功,false:失败 | | code | String | 响应码。0代表成功 | | errcode | String | 错误码。0代表成功(可忽略) | | msg | String | 响应信息 | | msgShowType | String | 信息显示类型。默认“none” | | secrit | String | 秘钥信息。注意此处secrit单词拼写错误(原词为:secret),请使用 secrit获取结果 | | spk | String | 系统公钥信息 | **返回错误示例一** ``` { "msg": "ok", "errcode": "1", "code": -1, "msgShowType": "none", "errmsg": "passowrd error:null & sysadmin", "status": false } ``` **返回错误示例二** ``` { "msg": "ok", "errcode": "1", "code": 0, "msgShowType": "none", "errmsg": "注册失败没有在找到正确的APPID:EEAA5436-7577-4BE0-8C6C-89E9D888", "status": false } ``` --- **2、简要描述:向OA系统发送获取token请求** * 获取token接口 **请求URL:** * `http://xx.com/api/ec/dev/auth/applytoken` **请求方式:** * POST **请求头部参数:** | 参数名 | 必选 | 类型 | 说明 | | -------- | ------ | -------- | ----------------------------------------------------------------------------------- | | appid | 是 | string | 许可证号码 | | time | 否 | int | token过期时间(单位:秒,默认1800) | | secret | 是 | string | 注册许可证时返回的公钥spk对秘钥信息secrit进行加密。(注意此处参数名单词拼写正确) | **接口参数:无** **返回示例** ``` { "msg": "获取成功!", "code": 0, "msgShowType": "none", "status": true, "token": "770a10d8-0b15-492b-a614-b2c537b512e5" } ``` **返回参数说明** | 参数名 | 类型 | 说明 | | ------------- | --------- | ------------------------------------------- | | status | boolean | 响应状态。true:成功,false:失败 | | code | String | 响应码。0代表成功 | | msg | String | 响应信息 | | msgShowType | String | 信息显示类型。默认“none” | | token | String | 认证通过的token信息。(默认30分钟内有效) | **返回错误示例一** ``` { "msg": "认证信息错误!", "code": -1, "msgShowType": "none", "status": false } ``` **返回错误示例二** ``` { "msg": "解密失败!", "code": -1, "msgShowType": "none", "status": false } ``` --- **3、简要描述:通过token的方式认证调用ECOLOGY系统普通接口** * token使用演示接口,该API没有实际意义 **请求URL:** * `http://xx.com/api/接口地址` **请求方式:** * GET | POST | PUT | DELETE **请求头部参数:** | 参数名 | 必选 | 类型 | 说明 | | -------------- | ------------------------------ | -------- | ------------------------------------------------------------------------------------ | | token | 是 | string | token信息 | | appid | 是 | string | 许可证号码 | | userid | 否(除“非用户”接口外都必填) | string | 通过注册许可时返回spk公钥对userid进行加密生成的密文 | | skipsession | 否 | string | 是否跳过session拦截(用于“非用户”接口),1代表是,0代表否(缺省) | | Content-Type | 否 | string | POST请求必须设置Context-Type为”application/x-www-form-urlencoded; charset=utf-8” | **接口参数:按照接口规范编写** **返回示例** ``` { "msg": "ok", "code": 0, "msgShowType": "none", "status": true } ``` **返回参数说明** | 参数名 | 类型 | 说明 | | ------------- | --------- | -------------------------------- | | status | boolean | 响应状态。true:成功,false:失败 | | code | String | 响应码。0代表成功 | | msg | String | 响应信息 | | msgShowType | String | 信息显示类型。默认“none” | **返回错误示例一** ``` { "msg": "token:不存在或者超时a25ed7ba-6027-424d-96ec-99daef56a51d", "code": -1, "msgShowType": "none", "status": false } ``` Last modification:March 8, 2024 © Allow specification reprint Support Appreciate the author AliPayWeChat Like 如果觉得我的文章对你有用,请随意赞赏