Appearance
第14章 用户身份认证
业务概述
之前实现开户业务时,系统只是要求用户填写了个人姓名和身份证信息,并没有进行身份认证和校验。这里面就存在着各种风险,例如:假名,盗用他人身份证等等。

特别是对于借款人来说,系统必须对其身份进行认证和校验,否则会对后续交易产生较大风险。系统进行身份认证和校验的时机,一个是在开户时进行,另一个在发标(交易的第1步)时进行,但考虑到有些用户即使开户也不一定会进行交易(例如:发标),所以把身份认证和校验放在发标时实现。
更新后的发标流程

操作流程图
- 填写借款申请

- 用户上传身份证照片

- 提交身份证信息

- 申请完毕,等待审核

需求分析
业务流程时序图
- 文件服务是专门用于处理文件上传、下载的微服务,可以为万信金融P2P项目的各个业务模块提供文件服务。
- 百度AI是一个第三方开发平台,能够提供各种智能技术,例如:语音识别,图像识别,文字识别等等。

业务流程简述
第一阶段:识别身份证(图中1.1-1.5)
- 前端携带身份证图片信息请求用户中心
- 用户中心请求百度AI平台进行识别
- 返回识别结果给前端
第二阶段:获取上传凭证(图中2.1-2.4)
- 前端请求用户中心获取上传授权
- 用户中心生成上传授权并返回
第三阶段:上传身份证(图中3.1-3.2)
- 前端携带上传凭证和照片请求文件服务,文件服务保存照片到七牛云上
- 返回上传结果给前端
第四阶段:保存身份证信息(图中3.3-3.5)
- 前端请求用户中心保存身份证信息
- 用户中心保存身份证照片标识等
- 返回前端保存成功
部署文件服务
文件服务是抽取出来的专门用于处理文件上传、下载的微服务,可以为万信金融 P2P 项目的各个业务模块提供文件服务。该服务默认采用七牛云作为文件存储源,将来也会和百度云、阿里云做对接,成为一个通用的、独立的文件微服务。
项目搭建与环境准备
Java 1.8+、MySQL 5.6.5+
初始化数据库
初始化 sql 脚本:
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
CREATE DATABASE `p2p_file` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
USE p2p_file;
DROP TABLE IF EXISTS `fileobject`;
CREATE TABLE `fileobject` (
`ID` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT '主键',
`fileName` VARCHAR ( 50 ) DEFAULT NULL COMMENT '原文件名',
`origin` VARCHAR ( 20 ) NOT NULL COMMENT '存储源',
`resourceKey` VARCHAR ( 100 ) NOT NULL COMMENT '文件key',
`flag` VARCHAR ( 10 ) NOT NULL COMMENT '正反面',
`downloadUrl` VARCHAR ( 200 ) DEFAULT NULL COMMENT '文件下载地址',
`isProtect` TINYINT ( 1 ) NOT NULL COMMENT '公有还是私有',
`uploaddate` datetime NOT NULL COMMENT '上传日期',
PRIMARY KEY ( `ID` )
) ENGINE = INNODB DEFAULT CHARSET = utf8;
SET FOREIGN_KEY_CHECKS = 1;IDE 导入工程
使用 IDEA 或者其他的 IDE 工具导入 wanxinp2p-file-service 工程

修改配置(数据库)
由于在上传文件时,需要把文件信息保存到 p2p_file 数据库的 fileobject 表中,因此需要修改 application.yml 文件中数据库相关配置。
yml
...
datasource:
url: jdbc:mysql://localhost:3306/p2p_file?useUnicode=true&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
...文件存储服务
注册七牛云对象存储服务
本项目默认使用七牛云(对象存储服务)来存储文件,需要自行注册并登录:https://www.qiniu.com/products/kodo。
- 登录到个人控制台后,需要点击左侧菜单中的“对象存储”中的【空间管理】,新增存储空间。

注:创建空间前需要进行实名认证
- 创建成功,获取融合 CDN 测试域名

- 获取七牛云服务秘钥,在编码过程中需要使用

修改配置(文件存储)
wanxinp2p-file-service 工程的功能均已实现,只需要修改项目中的 application.yml 配置文件,替换AK、SK、域名即可
yml
...
my:
file:
qiniu:
secretKey: key
accessKey: accessKey
domainOfBucket: http://测试域名
...用户服务配置使用文件服务
在上传文件之前,需要申请上传凭证,Java 代码中需要知道存储源和存储空间名字。登录 Apollo,找到 consumer-service 项目,关联名称空间:micro_service.files(如没有,则创建即可),并进行如下配置:
properties
# 固定写法
my.file.origin = qiniu
# 与具体个人七牛云中某存储空间名称保持一致
my.file.bucket = p2p-wanxin后面实现文件上传功能后,在内容管理中可以上传的文件,如下图所示。红框中的文件名是每个文件的唯一标识,会返回给用户中心服务,并保存到 p2p_consumer 数据库的 consumer_details 表中。

接口说明
wanxinp2p-file-service 项目作为独立的文件服务,已经实现了文件上传和下载,不需要再做功能实现,直接使用即可。要了解相关接口,启动服务后访问:http://localhost:56082/farming/swagger-ui.html,也可以直接查看项目源码。
百度 AI 服务
注册并登录百度AI
访问 https://login.bce.baidu.com,自行注册并登录(可以尝试短信验证码快捷登录)
文字识别配置
- 选择【产品服务】 -> 【人工智能】 -> 【文字识别】

- 创建应用

- 填写应用名称和类型,提交请求

- 获取 AppID, API Key 和 Secret Key

使用百度 AI
引入依赖
在用户中心服务(consumer-service)的 pom.xml 文件中引入百度 AI 的依赖
xml
<!-- 百度 AI -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.8.0</version>
</dependency>apollo 配置
登录 Apollo,对 consumer-service 项目中的 micro_service.files 中增加以下配置项(具体配置值根据实际情况配置):
properties
my.file.baidu.appid = 12345678
my.file.baidu.ak = mie83nKu3i8fn
my.file.baidu.sk = Ikkiw8cvIe389fjifkdnvbioidki第一阶段:识别身份证
此阶段,用户中心请求百度 AI 识别身份证,在用户中心定义识别身份证照片接口,接口描述如下
- 前端提交身份证照片到用户中心
- 用户中心请求百度 AI 进行身份证识别
- 百度 AI 返回识别结果给用户中心
- 用户中心响应前端返回识别结果
百度识别功能实现:请参考百度 AI 官方文档、身份证识别文档
识别身份证接口定义
在 wanxinp2p-api 工程的 ConsumerApi 接口中,定义 imageRecognition 识别身份证方法:
java
/**
* 提交身份证图片给百度AI进行识别
*
* @param file 被上传的文件
* @param flag 身份证正反面 取值front 或 back
* @return Map集合 识别成功后把身份证上的姓名和身份证号存到map中返回
*/
RestResponse<Map<String, String>> imageRecognition(MultipartFile file, String flag);功能实现(待完成!)
业务层
- 修改
ConsumerService接口,增加图片识别方法imageRecognition
java
/**
* 提交身份证图片给百度AI进行识别
*
* @param file 被上传的文件
* @param flag 身份证正反面 取值front 或 back
* @return Map集合 识别成功后把身份证上的姓名和身份证号存到map中返回
*/
Map<String, String> imageRecognition(MultipartFile file, String flag);- 在
ConsumerServiceImpl类中实现该方法
java
请求控制层
第二阶段:获取上传凭证(待完成!)
要想通过文件服务上传文件,必须获得上传凭证。在用户中心定义获取上传凭证接口,接口描述如下
- 向文件服务请求获取上传凭证
- 响应前端返回凭证
接口定义如下
在ConsumerApi接口中,定义applyUploadCertificate方法:
java
/**
* 申请获得上传凭证
* @return
*/
RestResponse<String> applyUploadCertificate();在ConsumerController类中实现该方法:
java
@Override
@ApiOperation("申请获得上传凭证")
@GetMapping("/my/applyUploadCertificate")
public RestResponse<String> applyUploadCertificate(){
return null;
}功能实现:请参考文件服务farming中的TokenController,需要通过RestTemplate或OkHttpClient往这里发请求。
第三阶段:上传身份证
前端携带之前获得的上传凭证,请求文件服务上传身份证照片,由于上传功能已经在文件服务中实现,所以这里只需要对前端做出调整(开启身份认证界面)即可。找到 wanxinp2p-web-app 工程的 borrow.vue 文件,然后将下图的注释去掉即可。

第四阶段:保存身份证信息(待完成!)
文件上传成功后,前端会接收到文件服务返回的结果和文件标识,然后前端携带这些数据请求用户中心保存身份证信息。
在用户中心定义保存身份证信息接口:
1、接口描述
- 接受前端提交的身份证信息
- 用户中心校验身份证信息是否和之前开户信息一致
- 用户中心保存身份证照片标识
- 返回结果给前端
2、接口定义
在ConsumerApi接口中,定义saveConsumerDetails方法:
java
/**
* 保存用户详细信息(主要存储身份证文件标识)
* @param consumerDetailsDTO 封装用户详情信息
* @return
*/
RestResponse<String> saveConsumerDetails(ConsumerDetailsDTO consumerDetailsDTO);在ConsumerController类中实现该方法:
java
@Override
@ApiOperation(value="保存用户详细信息", notes="主要存储身份证文件标识")
@ApiImplicitParams({
@ApiImplicitParam(name = "consumerDetailsDTO", value = "用户详细信息", dataType = "ConsumerDetailsDTO", paramType = "body")})
@PostMapping("/my/saveConsumerDetails")
public RestResponse<String> saveConsumerDetails(@RequestBody ConsumerDetailsDTO consumerDetailsDTO){
//... ...
return RestResponse.success("保存成功");
}该阶段涉及到新的类有:ConsumerDetailsDTO、ConsumerDetails、ConsumerDetailsService、ConsumerDetailsServiceImpl、ConsumerDetailsMapper