微服务与人证核身,碰撞出不一样的“烟火”
FunctionGraph+OBS+FRS+IVS实现人证核身
目录
- 场景设计
- 方案架构图
- 方案设计
- 云服务介绍
- 环境准备
- 开发流程
- 1.客户端开发——上传图片/视频到OBS
- 2.FunctionGraph函数代码开发
- 3.下载OBS对象+Base64编码
- 4.FRS活体检测
- 5.IVS人证核身
- 6.SMN发布结果消息
- 7.客户端开发——SMN之HTTP(S)终端接口开发
- 8.FunctionGraph函数整合
- 实现效果
- 部署测试
一、场景设计
客户通过页面上传人物照片、视频到OBS并触发FunctionGraph函数,函数调用FRS人脸识别服务判断是否为真人,如果是真人继续调用IVS人证核身服务校验身份真实性,最后通过SMN将结果消息发布出去。
方案架构图
二、方案设计
创建FunctionGraph函数,并为该函数配置OBS触发器,上传图片或视频到OBS后触发FunctionGraph函数,函数下载OBS对象并调用FRS进行活体检测,活体检测通过后函数再调用IVS进行人证核身,最后函数通过SMN发布人证核身结果消息。
云产品提供服务 | 作用 |
---|---|
OBS对象操作 | 实现上传/下载 图片/视频 |
FunctionGraph配置OBS触发器 | 实现OBS上传时触发函数 |
FunctionGraph创建Java函数 | 创建Java语言的函数 |
FRS活体检测 | 对图片或视频进行动作/静默活体检测 |
IVS认证核身标准版 | 实现对上传的人脸图片进行身份验证 |
SMN发送HTTP(S)消息 | 实现将结果发送到HTTP(S)终端 |
三、云服务介绍
华为云OBS: 对象存储服务(Object Storage Service,OBS)是一个基于对象的海量存储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力,使用时无需考虑容量限制,并且提供多种存储类型供选择,满足客户各类业务场景诉求。产品页面
华为云FunctionGraph:函数工作流(FunctionGraph)是一项基于事件驱动的函数托管计算服务。通过函数工作流,只需编写业务函数代码并设置运行的条件,无需配置和管理服务器等基础设施,函数以弹性、免运维、高可靠的方式运行。产品页面
华为云FRS:人脸识别服务(Face Recognition Service),能够在图像中快速检测人脸、分析人脸关键点信息、获取人脸属性、实现人脸的精确比对和检索。该服务可应用于身份验证、电子考勤、客流分析等场景。产品页面
华为云IVS:人证核身服务(Identity Verification Solution)将用户本人与身份证信息关联起来,应用人脸识别与文字识别等技术,对接权威数据库,支持基于二要素(姓名、身份证)认证或三要素(人脸、姓名、身份证)认证,实现对身份真实性的精准核验。产品页面
华为云SMN:消息通知服务(Simple Message Notification)为用户提供快速简便、稳定可靠、简化运维、高可扩展、安全可信的消息通知能力。最终用户可以通过HTTP、HTTPS、邮件、短信、触发函数执行、即时通讯工具等方式接收通知信息。华为云用户也可以在应用之间通过消息通知服务实现应用的功能集成,降低系统的复杂性。产品页面
四、环境准备
| 开发语言:Java
| 开发环境:jdk1.8 maven3.6.3
| 华为云环境:注册云账号,并完成实名认证
五、开发流程
| 分为客户端开发和FunctionGraph的Java函数开发。
1、客户端开发–上传图片/视频到OBS
-
华为云OBS服务控制台创建桶用来存储人脸图片或视频
-
如果涉及视频需要压缩上传,需要配置在线解压策略(具体桶中->数据处理>在线解压)
-
拿到OBS的maven依赖坐标,使用SDK开发上传OBS对象客户端,这里文件传到固定的文件夹下,并使用固定对象名命名,比如face。帮助文档
-
上传对象方法代码参考
public void uploadFile(MultipartFile multipartFile){
String endPoint = "https://终端节点";
String ak = "ak";
String sk = "sk";
//1.创建OBS客户端对象
ObsClient obsClient = new ObsClient(ak, sk, endPoint);
//2.获取文件输入流
InputStream in = null;
try {
in = multipartFile.getInputStream();
//3.上传对象,后面根据该对象名下载对象,保持上传下载一致
PutObjectResult putObjectResult = obsClient.putObject("桶名", "对象名", in);
System.out.println(putObjectResult);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
if (in!=null){
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2、FunctionGraph函数代码开发
(1)FunctionGraph函数时序图
(2)Java函数环境搭建
-
创建maven项目,导入FunctionGraph提供的Runtime依赖
操作指导 -
创建FunctionGraph Java函数,并配置OBS触发器。
3、下载OBS对象+Base64编码
- 从OBS下载对象并进行Base64编码,后面使用该Base64编码结果进行活体检测。
- 导入OBS的Maven依赖。可以从SDK中心查询依赖坐标
- 下载对象+Base64编码示例代码:
public static String download() {
//1.相关配置数据
String endPoint = "https://终端节点";
String ak = "ak";
String sk = "sk";
//2.创建ObsClient实例
final ObsClient obsClient = new ObsClient(ak, sk, endPoint);
//对象名保持和上传对象名一致
ObsObject obsObject = obsClient.getObject("桶名", "对象名");
//3.读取对象内容
ByteArrayOutputStream bos = null;
InputStream input = null;
String imageStr = null;
try {
System.out.println("Object content:");
input = obsObject.getObjectContent();
byte[] b = new byte[1024];
bos = new ByteArrayOutputStream();
int len;
while ((len = input.read(b)) != -1) {
bos.write(b, 0, len);
}
//4.Base64编码
byte[] data = new byte[bos.size()];
data = bos.toByteArray();
imageStr = new String(Base64.encodeBase64(data));
System.out.println(imageStr);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return imageStr;
}
4、FRS活体检测
- 活体检测,判断图片或视频中的人物是否为真人活体。对Base64编码后的结果进行活体检测,图片使用静默活体检测,视频使用动作活体检测。以图片对应的静默活体检测为例,使用SDK开发。
//方法参数imageStr:人像图片Base64编码
public static DetectLiveFaceByBase64Response detectLive(String imageStr) {
//1.配置基本信息
ICredential credential = new BasicCredentials().withAk("ak").withSk("sk");
FrsClient client = FrsClient.newBuilder()
.withCredential(credential)
.withRegion(FrsRegion.valueOf("区域")) // 选择服务所在区域,如华北-北京四: FrsRegion.valueOf("cn-north-4")
.build();
//2.通过base64编码进行活体检测
DetectLiveFaceByBase64Request request = new DetectLiveFaceByBase64Request();
LiveDetectFaceBase64Req body = new LiveDetectFaceBase64Req();
body.withImageBase64(imageStr);
request.withBody(body);
DetectLiveFaceByBase64Response response = null;
try {
response = client.detectLiveFaceByBase64(request);
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
5、IVS人证核身
- 这里用到IVS标准版(三要素)对图片中人物进行身份认证,这里用到的图片Base64是FRS活体检测返回的结果中的图片Base64编码。
//方法参数imageStr:人像图片Base64编码
public static String ivsVerify(String imageStr) {
//1.配置基本信息
ICredential credential = new BasicCredentials().withAk("ak").withSk("sk");
IvsClient client = IvsClient.newBuilder()
.withCredential(credential)
.withRegion(IvsRegion.valueOf("区域"))// 选择服务所在区域,如华北-北京四就是 FrsRegion.valueOf("cn-north-4")
.build();
DetectStandardByIdCardImageRequest request = new DetectStandardByIdCardImageRequest();
IvsStandardByIdCardImageRequestBody body = new IvsStandardByIdCardImageRequestBody();
List<ReqDataByIdCardImage> listIvsStandardByIdCardImageRequestBodyDataReqData = new ArrayList<>();
listIvsStandardByIdCardImageRequestBodyDataReqData.add(
new ReqDataByIdCardImage()
.withIdcardImage1("身份证人像面图片Base64")
.withFaceImage(imageStr)
);
IvsStandardByIdCardImageRequestBodyData databody = new IvsStandardByIdCardImageRequestBodyData();
databody.withReqData(listIvsStandardByIdCardImageRequestBodyDataReqData);
Meta metabody = new Meta();
//唯一标识此次请求的ID,用户自定义,不超过64位
metabody.withUuid(UUID.randomUUID().toString());
body.withData(databody);
body.withMeta(metabody);
request.withBody(body);
String result = null;
try {
//2.调用服务
DetectStandardByIdCardImageResponse response = client.detectStandardByIdCardImage(request);
System.out.println(response.toString());
//result取值:valid-成功;invalid-失败
result = response.getResult().getRespData().get(0).getVerificationResult();
} catch (Exception e) {
e.printStackTrace();
}
//3.返回人证核身结果
return result;
}
6、SMN发布结果消息
- 这里用SMN向HTTP(S)终端发送消息,将人证核身结果发布到指定的URL地址。
- 开通服务(创建主题+创建订阅)控制台
-
导入IVS的Maven依赖。可以从SDK中心查询依赖坐标
-
SMN发布消息示例代码:
//方法请求参数msgContent:消息内容
public static void sendMsg(String msgContent){
String ak = "ak";
String sk = "sk";
//创建SMN客户端
ICredential credential = new BasicCredentials().withAk(ak).withSk(sk);
SmnClient client = SmnClient.newBuilder()
.withCredential(credential)
.withRegion(区域)//如华北-北京四:SmnRegion.CN_NORTH_4
.build();
//创建请求
PublishMessageRequest publishMessageRequest = new PublishMessageRequest();
//创建请求体
PublishMessageRequestBody body = new PublishMessageRequestBody();
body.withMessage(msgContent);
body.withSubject("主题");
publishMessageRequest.withTopicUrn("主题URN,可在控制台获取");
publishMessageRequest.withBody(body);
//执行请求
PublishMessageResponse response = client.publishMessage(publishMessageRequest);
System.out.println(response);
}
7、客户端开发–SMN之HTTP(S)终端接口开发
-
HTTP(S)终端对应的URL接口需要根据type参数判断是确定订阅、消息或是取消订阅。
-
接口示例代码:
@PostMapping("/smn") //该接口完整地址就是创建时配置的终端地址
public void subscriptionConfirmation2(@RequestBody SubscriptionReq subscriptionReq,HttpServletRequest request,HttpServletResponse response){
System.out.println(subscriptionReq);
try{
//1.获取参数,封装到MAP中
Map<String, String> parameterMap = BeanUtils.describe(subscriptionReq);
String signing_cert_url = parameterMap.get("signing_cert_url");
String signature = parameterMap.get("signature");
//2.检验消息签名
boolean flag = SmnUtil.isMessageValid(signing_cert_url, signature, parameterMap);
//3.判断是订阅还是发布消息
String type = parameterMap.get("type");
if ("SubscriptionConfirmation".equals(type)){
//4.访问订阅确认页面
String map = restTemplate.getForObject(parameterMap.get("subscribe_url"), String.class);
System.out.println(map);
}else if ("Notification".equals(type)){
//5.消息,打印消息
System.out.println(parameterMap);
}else{
//6.取消订阅
}
}catch (Exception e){
e.printStackTrace();
}
}
- 接口接收请求参数实体类可参考:
@Data //Lombok注解
public class SubscriptionReq {
private String type;
private String signature;
private String subject;
private String topic_urn;
private String message_id;
private String signature_version;
private String message;
private String subscribe_url;
private String signing_cert_url;
private String timestamp;
}
8、FunctionGraph函数整合
-
在触发函数对应的方法中调用上面服务方法,实现认证核身认证流程。即在搭建的FunctionGraph Java函数项目中的TriggerTests.java中的apiTest方法中编写人证核身业务逻辑。
-
TriggerTests代码:
import java.util.HashMap;
import java.util.Map;
import com.huawei.services.runtime.Context;
import com.huawei.services.runtime.entity.apig.APIGTriggerEvent;
import com.huawei.services.runtime.entity.apig.APIGTriggerResponse;
import com.huawei.utils.FrsUtils;
import com.huawei.utils.IvsUtils;
import com.huawei.utils.ObsUtils;
import com.huawei.utils.SmnUtils;
import com.huaweicloud.sdk.frs.v1.model.DetectLiveFaceByBase64Response;
public class TriggerTests {
//functionGraph函数触发方法
public APIGTriggerResponse apigTest(APIGTriggerEvent event, Context context) {
//1.下载对象,并得到base64编码后结果
String imageBase64 = ObsUtils.download();
//2.活体检测
DetectLiveFaceByBase64Response response = FrsUtils.detectLive(imageBase64);
Boolean alive = response.getResult().getAlive();
//3.人证核身
String msg = null;
if (alive) {
//活体检测成功
String result = IvsUtils.ivsVerify(response.getResult().getPicture());
//result取值:valid-成功;invalid-失败
msg = "valid".equals(result) ? "人证核身成功!是XXX本人。" : "人证核身失败!";
System.out.println(result+"--"+msg);
//4.发送结果信息
SmnUtils.sendMsg(msg);
} else {
msg = "活体检测失败!";
System.out.println(msg);
//发送结果消息
SmnUtils.sendMsg(msg);
}
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
return new APIGTriggerResponse(200, headers, msg);
}
}
六、实现效果
1、部署测试
- 将FunctionGraph Java函数对应项目打成jar包。参照帮助文档
- FunctionGraph创建Java函数,并配置OBS触发器(对应:开发流程->二、FunctionGraph函数代码开发->1、Java函数环境搭建)。
- FunctionGraph上传项目jar包到函数。
- 通过开发的客户端上传图片或视频到OBS。
- 在客户端刷新接收SMN消息的HTTP(S)终端接口,查看结果信息;查看FunctionGraph日志。
- 点赞
- 收藏
- 关注作者
评论(0)