**对接人：李永锋**

图片预览链接/preview接口，去除url中的 type=imgs 就可以看接口返回值了

鉴权结果

**数据源拼接附件地址位置**

com.weaver.ebuilder.form.remote.datasource.service.impl.RuntimeEBFormLogicFieldServiceImpl#parseBrowserData(java.util.List\<[java.util.Map](http://java.util.Map)\<java.lang.String,java.lang.Object\>\>, java.util.List\<com.weaver.ebuilder.datasource.api.entity.LogicField\>)

permissionType →ebuilderform→result

**附件refId更正位置**

[com.weaver.ebuilder.form.data.service.impl.data](http://com.weaver.ebuilder.form.data.service.impl.data).DataServiceImpl#handlerDocPermission(java.lang.Long, java.lang.Long, java.lang.Long, boolean, [java.util.Map](http://java.util.Map)\<java.lang.String,java.lang.Object\>, com.weaver.teams.domain.user.SimpleEmployee, java.util.List\<com.weaver.ebuilder.form.client.entity.field.Field\>, java.lang.Long)

**拼接附件预览链接**

com.weaver.ebuilder.form.fieldinterface.util.FileFieldUtil#buildFileFieldSpan

## 一、E10整体附件鉴权逻辑介绍

> E10附件本身没有权限的（即附件服务不会对附件做任何权限校验）

知识组在进行附件鉴权时，逻辑如下

1. 如果附件有关联文档，直接查找附件所关联文档的附件操作权限
2. 然后根据附件的鉴权模块，到对应的鉴权模块查找权限

找模块的依据是两个：

1.鉴权链接上拼了 authModule=ebuilderform 不管附件是不是我们的都会找我们鉴权

2.知识库里存了这个附件是ebuilderform的

最后将以上两步的附件权限取一个并集返回。

### 附件鉴权模块的判定

前端发起的附件预览或者下载请求，一般都会在连接中拼接一个authMoudle字段（我们模块是ebuilderform）

在没有拼接附件鉴权模块的情况下，会查找附件的来源模块去对应服务进行反向鉴权（file库 fileObj表 module 字段）

## 二、e-Builder中的附件鉴权实现

### 2.1附件鉴权业务逻辑

#### 2.1.1表单字段中关联的附件的鉴权

表单中关联附件的权限受数据共享权限中的附件下载权限控制，有数据查看权限时默认有附件预览权限，其他权限需要额外勾选

#### 2.1.2非表单字段中关联的附件

e10中，许多附件由一些特殊场景生成（如图片单选字段中的附件等）这些附件是没有和eb数据进行关联的；同时这些附件的所属模块是ebuilderform的情况下：eb服务会直接赋予预览和下载权限。否则一律没有附件权限

#### 2.1.3虚拟表的附件权限

eb虚拟表的附件通过授权码的方式默认赋予当前操作者查看权限（具体需咨询当前负责虚拟表的开发人员）

#### 2.1.4 papi免登录附件鉴权

> 鉴权请求中的链接以 域名/papi开头，都会执行免登录鉴权逻辑，不论当前是否有登录人

分为一下两个场景：

1. 外部分发关联的附件数据，赋予下载和预览权限（无需判断附件的模块是否属于ebuilderform）
2. 如果附件的模块来源属于ebuilderform，则赋予预览和下载权限（逻辑同2.1.2中介绍一致）

### 2.2 附件鉴权代码实现方式

我们服务中所有的附件鉴权，都是知识组通过反向鉴权调用一下方法实现的

> com.weaver.ebuilder.form.remote.impl.matters.EbuilderPermissionExternalImpl#checkFileRight

#### 2.2.1常规附件鉴权

所有的附件鉴权方法都实现了 com.weaver.ebuilder.form.fileright.FileRightProcess 接口

实现 com.weaver.ebuilder.form.fileright.FileRightProcess#process 方法

然后组装到 com.weaver.ebuilder.form.fileright.FileRightHandler#processList 集合之中

通过迭代processList 的方式串行解析权限，一旦集合中有process 方法返回了true则鉴权链路结束返回当前权限项；

#### 2.2.2一些特殊的附件鉴权

一些鉴权请求的customParam中带有鉴权类型，

如果根据这个鉴权类型可以在 com.weaver.ebuilder.form.fileright.FileRightHandler#functionTypeEnumAbsFileRightProcessMap 中获取到鉴权方法，则直接执行对用的鉴权实现类的process 方法，执行权限，然后返回对应权限

#### 2.2.3附件鉴权实现类列表

（可能不全，以实际代码为准）

| 实现类 |  |
| --- | --- |
| com.weaver.ebuilder.form.fileright.rightimpl.AssociatedAuthorizationFileRightProcess | 数据关联授权 |
| com.weaver.ebuilder.form.fileright.rightimpl.CreateLayoutFileRightProcess | 新建布局临时授权 |
| com.weaver.ebuilder.form.fileright.rightimpl.DistriButeFileRightProcess | 外部分发相关附件鉴权 |
| com.weaver.ebuilder.form.fileright.rightimpl.WPSFileRightProcess | 表单wps编辑器上关联的附件单独的鉴权逻辑 |
| com.weaver.ebuilder.form.fileright.rightimpl.PapiFileRightProcess | 免登录的附件鉴权请求 |
| com.weaver.ebuilder.form.fileright.rightimpl.FileUploadRightProcess | 附件上传鉴权请求，这种鉴权请求是没有给附件id的 |
| com.weaver.ebuilder.form.fileright.rightimpl.PublicFileRightProcess | 未关联eb数据id的附件鉴权，refId未传递，customParam中没有dataId |
| com.weaver.ebuilder.form.fileright.rightimpl.EbDataRefFileRightProcess | 常规附件鉴权，需要判断这个附件是否真是存在于表单字段中 |
| com.weaver.ebuilder.form.fileright.rightimpl.SecretKeyRightProcess | 在鉴权请求中拼接鉴权token，鉴权时根据token解析权限；目前主要用于虚拟表附件的鉴权 |

### 新建布局临时授权

新建布局临时授权,支持从配置文件中配置开启;

如果开启后,就会在/getDetail请求中返回一个 secretKey 校验时再检验这个key就可以了

### 2.3问题排查支持和一些可选项

#### nacos配置项

weaver.ebuilder.form.fileright.file-right-log 默认鉴权报错的请求会记录到ebdf\_file\_right\_request表中

weaver.ebuilder.form.fileright.file-right-level 附件鉴权级别 小于等于0：强权限校验：如果是建模数据关联的附件，会强制校验此附件是否和数据关联 小于等于98：默认鉴权级别 小于等于99：弱权限鉴权：如果判断附件是eb附件直接放权，如果非eb附件则根据入参规则进行校验 99以上：直接放权

weaver.ebuilder.form.fileright.enable-secret-key secretKey密文附件鉴权 的方式对整个系统的附件eb都可能会进行赋权，这里直接从nacos中一键关闭此功能

**其余可选项可以参考 com.weaver.ebuilder.form.base.config.refresh.EbuilderFileRightConfig**

#### 问题排查

**附件的鉴权报错，一般不会被try catch**，这样如果鉴权失败一方面可以到ebdf\_file\_right\_request表中查看日志，也可以直接复制附件鉴权链接到浏览器新窗口，知识组会将报错直接打印在页面上

## 三、拓展一个附件鉴权业务点

### 1.继承 com.weaver.ebuilder.form.fileright.AbsFileRightProcess 抽象类

这里建议不要直接实现 com.weaver.ebuilder.form.fileright.FileRightProcess 接口

而是实现 com.weaver.ebuilder.form.fileright.AbsFileRightProcess 抽象类

### 2.实现com.weaver.ebuilder.form.fileright.FileRightProcess#process 方法，完成业务逻辑处理

> 此方法入参是一个 com.weaver.ebuilder.form.fileright.FileRightContext 上下文对象，如果缺失必要参数可以自行添加，这个上下文对象是贯穿整个鉴权链路，涉及所有实现类使用的，所以属性都设置成final的，不可随意更改上下文的属性

> 处理的鉴权结果 需要设置到 com.weaver.ebuilder.form.fileright.FileRightContext#result 属性中，**不要将无权限项设置到result中**，防止覆盖上游鉴权链路的结果
> 
> 同时：这里建议**直接调用 com.weaver.ebuilder.form.fileright.AbsFileRightProcess#putResult 方法设置** 此方法不会影响上游实现类的鉴权结果

> 如果可以判断此次鉴权请求，到这里就应该结束，不需要再走其他实现类处理结果的情况下，process方法直接返回 true，否则返回false

## 3.将实现类的bean添加到鉴权链路

在 com.weaver.ebuilder.form.fileright.FileRightHandler#buildHandle 方法中，会组装两个鉴权实现类集合

### com.weaver.ebuilder.form.fileright.FileRightHandler#processList

**鉴权实现类一般必须添加到这个list之中**，实现类的排序并非先加入的实现类放在前面，而是根据可能的鉴权耗时进行排序的，平均鉴权耗时越大的鉴权实现类越靠后；

目前所有的实现类中耗时都比较小，耗时最大的可能就是 EbDataRefFileRightProcess，如果新的鉴权实现类没有太多的rpc或者查库操作，可以放在 EbDataRefFileRightProcess之前

### com.weaver.ebuilder.form.fileright.FileRightHandler#functionTypeEnumAbsFileRightProcessMap

此map的key是鉴权 com.weaver.ebuilder.form.fileright.PermissionCustomParam#function 属性，如果前端请求参数中包含这个属性

并且，鉴权请求仅需要这个属性对应的实现类来完成鉴权逻辑的话，可以加入到此map中

## 鉴权日志

如果鉴权发生报错,日志会记录在ebdf\_file\_right\_request表中

# 自定义附件鉴权链接

url里面传一个 customParam  是一个json对象   
  
{  
    "dataId" : "123456"  
    "objId" : "12345"  
}  
  
进行url转换后大概张这样:  
customParam=%7B%22dataId%22%3A12345%2C%22objId%22%3A12345%7D  
dataId是这个附件所在的数据id
