# Rest三方互信(Since V9.0 NEXT)

# 介绍

基于接口访问安全考虑,自V8.2SP1(包含)起,将部分重要接口设置为必须通过三方互信方式才能调用。自V9.0 NEXT(包含)起,为了更进一步提高安全性,对三方互信接口实现做了一定调整。

# 说明

A6产品线不支持Rest远程调用。如需定制化开发,需要使用A8版本。

# token失效时长

不同版本可能存在差异,以v8.2sp1 20221013版本为例,时长为23分钟

# 什么时候需要用?

出现如下 场景1 或者 场景2,且接口被配置到接口配置文件中

场景1:OA由V8.2SP1(不包含)以下版本升级至V9.0 NEXT及后续版本,原本可正常调用的rest接口出现401错误(如图)

1723601599137.png

场景2:在V8.2SP1、V9.0两个版本已经实现了三方互信交互改造,但是没有勾选校验IP并配置绑定IP,升级至V9.0 NEXT及后续版本后,在获取调用获取token接口出现500错误(如图),提示“登录IP异常,请通过管理员帐号检查三方互信IP绑定情况!”

1723618303439.png

接口配置文件:ApacheJetspeed\webapps\seeyon\WEB-INF\cfgHome\base\dataSynchronizationAccessInfo.txt

## This file defines the rest interface for third party to access OA through channel token

## form/getformdata/{summaryIdOrAffairId}
com.seeyon.ctp.rest.resources.FormResource#getformdata#java.lang.Long

## affairData/pending/code/{memberCode}
com.seeyon.ctp.rest.resources.AffairDataV2Resource#getPendingList#java.lang.String

## interface for v8
com.seeyon.ctp.rest.resources.V8TicketResources#checkTicket#java.lang.String
com.seeyon.ctp.rest.resources.V8TicketResources#getDomainIds#java.lang.String,java.lang.Long
com.seeyon.ctp.rest.resources.V8TicketResources#getPluginInfo#java.lang.String
com.seeyon.ctp.rest.resources.V8TicketResources#getSysVarList#java.lang.String
com.seeyon.ctp.rest.resources.V8TicketResources#getSysByName#java.lang.String,java.lang.String,java.lang.Long
com.seeyon.ctp.rest.resources.V8TicketResources#getMemberRoles#java.lang.String,java.lang.Long


## discard old deprecate rest
## pending
com.seeyon.ctp.rest.resources.AffairDataResource#getPendingList#java.lang.String,java.lang.Long,java.lang.String
## pending/code/{memberCode}
com.seeyon.ctp.rest.resources.AffairDataResource#getPendingList#java.lang.String,java.lang.String
## pendingbyapp
com.seeyon.ctp.rest.resources.AffairDataResource#getPendingListByApp#java.lang.String,java.lang.Long,java.lang.Integer
## pendingCountbyapp
com.seeyon.ctp.rest.resources.AffairDataResource#getPendingListCountByApp#java.lang.String,java.lang.Long,java.lang.Integer
## donebyapp
com.seeyon.ctp.rest.resources.AffairDataResource#getDoneListByApp#java.lang.String,java.lang.Long,java.lang.Integer
## done
com.seeyon.ctp.rest.resources.AffairDataResource#getDoneList#java.lang.String,java.lang.Long
## done/code/{memberCode}
com.seeyon.ctp.rest.resources.AffairDataResource#getDoneListByMemberCode#java.lang.String,java.lang.String
## sent
com.seeyon.ctp.rest.resources.AffairDataResource#getSentList#java.lang.String,java.lang.Long
## sent/code/{meberCode}
com.seeyon.ctp.rest.resources.AffairDataResource#getSentListByMemberCode#java.lang.String,java.lang.String
## draft
com.seeyon.ctp.rest.resources.AffairDataResource#getDraftList#java.lang.String,java.lang.Long
## track
com.seeyon.ctp.rest.resources.AffairDataResource#getTrackList#java.lang.String,java.lang.Long
## track/code/{memberCode}
com.seeyon.ctp.rest.resources.AffairDataResource#getTrackListByMemberCode#java.lang.String,java.lang.String
## supervise
com.seeyon.ctp.rest.resources.AffairDataResource#getSuperviseList#java.lang.String,java.lang.Long
## data pulse
com.seeyon.ctp.rest.resources.BiinsideResource#hasAuthOfReport#java.util.Map
com.seeyon.ctp.rest.resources.MessageResource#sendMessageByLoginNameExt#java.util.Map
com.seeyon.ctp.rest.resources.VreportResource#getSysVarExt#java.lang.Long,java.lang.String
com.seeyon.ctp.rest.resources.DogResource#hasPlugin#java.lang.String

# 不想用三方互信能力怎么办?

在catalina_custom.sh或者catalina_custom.bat 脚本中增加jvm参数 -DisIgnoreDataSyncAccessCheck=TRUE

# 接口交互流程

1716273254867.png

第一步:三方系统调用“http(s)://{ip}:{port}/seeyon/rest/token/channel”接口 第二步:OA系统在返回前调用配置的回调接口,将token传递给三方系统 第三步:OA系统返回channel接口处理结果,告知三方互信是否验证通过 第四步:验证通过的情况下,拿第二步的token访问OA服务rest接口

注: 三方互信是否通过根据http的code状态是否等于200判断,即使三方互信接口内存在报错,只要可正常访问到该接口,也认为是验证通过

# 开发方案

# 创建三方互信ID

1723618721702.png

  • 登录系统管理员界面,在左侧导航栏选择 “信息集成配置”,进入“三方互信访问授权”界面。
  • 新建互信ID,回调地址为三方系统提供的一个可访问地址。其他配置与“REST用户管理”中创建rest账号一致

注:绑定IP并不一定是三方服务所在服务器IP,请参照产品升级手册确认IP

1726306989764.png

  • 授予模块访问权限

# 配置三方互信ID

参照如下参数说明调整脚本中的值后插入数据

字段名 类型 数据来源
id 数字 UUID,确保不重复即可
interface_name 字符串 需要使用的业务接口,配置到dataSynchronizationAccessInfo.txt中的内容
rest_id 数字 创建三方互信界面中的ID
ext 字符串 备注信息
create_time 时间 当前时间
update_time 时间 当前时间
insert into ctp_rest_access (id, interface_name, rest_id, ext, create_time, update_time) values (1601040833543491250, 'com.seeyon.ctp.rest.resources.FormResource#getformdata#java.lang.Long', 397624945116616, 'dataplus', '2024-08-14 10:00:00', '2024-08-14 10:00:00');

# 三方系统代码开发

以springboot服务为例,细节处自行调整

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: 开放平台
 * @date: 2024-08-14
 * @description: 获取token并调用业务接口实现类
 */
@RestController()
@RequestMapping("/restTest")
public class RestTestController {

    @GetMapping("/test")
    public void test() throws Exception {
        // 获取token
        RestTemplate restTemplate = new RestTemplate();
        Map<String, Object> chanelBody = new HashMap<>();
        chanelBody.put("id", 397624945116616L); //根据实际情况调整
        chanelBody.put("secret", "a2bb6e04-f179-45dc-b051-ad45d9ae6c18"); //根据实际情况调整
        chanelBody.put("loginName", "xxx"); //根据实际情况调整,token绑定的人员,调用接口存在获取当前人员信息的场景下此字段必传,否则可以不用传

        HttpEntity<Object> tokenEntity = new HttpEntity<>(chanelBody);
        String tokenUrl = "http://192.168.225.26:30581/seeyon/rest/token/channel"; //根据实际情况调整
        restTemplate.exchange(tokenUrl, HttpMethod.POST, tokenEntity, String.class);

        //调用三方互信接口
        String channelUrl = "http://192.168.225.26:30581/seeyon/rest/form/getformdata/-4707313976826705432"; //根据实际情况调整
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", RestCallbackController.token);
        HttpEntity<Object> channelEntity = new HttpEntity<>(headers);
        ResponseEntity<String> channelRespose = restTemplate.exchange(channelUrl, HttpMethod.GET, channelEntity, String.class);
        System.out.println(channelRespose.getBody());

    }
}
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * @author: 开放平台
 * @date: 2024-08-14
 * @description: 三方服务提供的rest回调接口实现类
 */
@RestController
@RequestMapping("/thirdServer")
public class RestCallbackController {

    //三方互信token
    public static String token = "";

    @PostMapping("/callback")
    public void restCallback(@RequestBody Map<String, Object> data) {
        token = (String) data.get("token");
    }
}