springboot實(shí)現(xiàn)調(diào)用百度ocr實(shí)現(xiàn)身份識(shí)別+二要素校驗(yàn)功能
一、技術(shù)選型
OCR服務(wù):推薦使用百度AI
二、實(shí)現(xiàn)
1.注冊(cè)一個(gè)服務(wù)
百度智能云控制臺(tái)
https://console.bce.baidu.com/ai-engine/ocr/overview/index?_=1742309417611


填寫完之后可以獲取到app-id、apiKey、SecretKey這三個(gè)后面文件配置會(huì)用到

2、導(dǎo)入依賴
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.13</version>
</dependency>
<!-- 百度AI SDK(示例) -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.16.13</version>
</dependency>
<!--json依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.40</version>
</dependency>3、配置文件
spring:
servlet:
multipart:
max-request-size: 10MB # 文件上傳最大值
max-file-size: 10MB # 單個(gè)文件最大值
baidu:
ai:
app-id: ***** 換成自己的
secret-key: ***** 換成自己的
api-key: ***** 換成自己的4、編寫OCR工具類
import com.baidu.aip.ocr.AipOcr;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
@Component
public class OcrService {
@Value("${baidu.ai.app-id}")
private String appId;
@Value("${baidu.ai.api-key}")
private String apiKey;
@Value("${baidu.ai.secret-key}")
private String secretKey;
public Map<String, String> recognizeIdCard(MultipartFile file, boolean isFront) throws Exception {
AipOcr client = new AipOcr(appId, apiKey, secretKey);
// 讀取圖片字節(jié)
byte[] imgData = file.getBytes();
// 設(shè)置身份證正反面
String idCardSide = isFront ? "front" : "back";
// 設(shè)置其他識(shí)別選項(xiàng)(如果有)
HashMap<String, String> options = new HashMap<String, String>();
// 可以在這里添加其他選項(xiàng),例如:
// options.put("detect_direction", "true"); // 檢測(cè)圖像朝向
// 調(diào)用身份證識(shí)別接口
JSONObject res = client.idcard(imgData, idCardSide, options);
// 檢查返回結(jié)果
if (res == null || !res.has("words_result")) {
throw new Exception("OCR 識(shí)別失敗: 返回結(jié)果為空或不包含 words_result");
}
// 解析結(jié)果
Map<String, String> result = new HashMap<String, String>();
JSONObject words = res.getJSONObject("words_result");
// 根據(jù)正反面提取不同字段
if (isFront) {
result.put("姓名", words.optString("姓名", ""));
result.put("性別", words.optString("性別", ""));
result.put("民族", words.optString("民族", ""));
result.put("出生日期", words.optString("出生年月日", ""));
result.put("住址", words.optString("住址", ""));
result.put("身份證號(hào)", words.optString("公民身份號(hào)碼", ""));
} else {
result.put("簽發(fā)機(jī)關(guān)", words.optString("簽發(fā)機(jī)關(guān)", ""));
result.put("有效期限", words.optString("失效日期", ""));
}
return result;
}
}5、文件上傳接口
import com.alibaba.fastjson.JSON;
import com.cykj.service.OcrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/idcard")
/**
* 身份證識(shí)別控制器
* 提供身份證圖片上傳和識(shí)別功能
*/
public class IdCardController {
@Autowired
private OcrService ocrService;
/**
* 上傳身份證圖片并進(jìn)行識(shí)別
*
* @param frontFile 身份證正面圖片
* @param backFile 身份證反面圖片
* @return 身份證信息的Map,包括正面和反面的識(shí)別結(jié)果
*/
@PostMapping("/upload")
public ResponseEntity<?> uploadIdCard(
@RequestParam("frontFile") MultipartFile frontFile,
@RequestParam("backFile") MultipartFile backFile) {
System.out.println(frontFile);
System.out.println(backFile);
try {
// 識(shí)別正面信息
Map<String, String> frontInfo = ocrService.recognizeIdCard(frontFile, true);
System.out.println("Front Info: " + frontInfo);
// 識(shí)別反面信息
Map<String, String> backInfo = ocrService.recognizeIdCard(backFile, false);
System.out.println("Back Info: " + backInfo);
// 合并結(jié)果
Map<String, String> combined = new HashMap<String, String>();
combined.putAll(frontInfo);
combined.putAll(backInfo);
// 身份證校驗(yàn)(示例)
String idNumberJson = combined.get("身份證號(hào)");
//解析獲取身份證號(hào)
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(idNumberJson);
String idNumber = jsonObject.getString("words");
if (!validateIdCard(idNumber)) {
return ResponseEntity.badRequest().body("身份證號(hào)校驗(yàn)失敗");
}
return ResponseEntity.ok(combined);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(500).body("識(shí)別失敗: " + e.getMessage());
}
}
/**
* 簡(jiǎn)單身份證號(hào)校驗(yàn)(正則表達(dá)式)
*
* @param idNumber 身份證號(hào)碼字符串
* @return 校驗(yàn)通過返回true,否則返回false
*/
private boolean validateIdCard(String idNumber) {
String regex = "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$";
return idNumber != null && idNumber.matches(regex);
}
}三、前端寫個(gè)測(cè)試頁面
這邊的action路徑要改成自己的路徑
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8086/api/idcard/upload" method="post" enctype="multipart/form-data">
<input type="file" name="frontFile" accept="image/*" required>
<input type="file" name="backFile" accept="image/*" required>
<button type="submit">上傳并識(shí)別</button>
</form>
</body>
</html>
第一張為身份證正面(人)
第二張上傳為身份證反面(國(guó)徽那面)
測(cè)試成功在頁面和控制臺(tái)都可以看見自己提取出來的信息就成功啦!
四、二要素校驗(yàn)
身份證上傳也不能保證信息準(zhǔn)確,畢竟還可以進(jìn)行p圖技術(shù)進(jìn)行修改嘛
為了保證信息的正確,就得要引入二要素校驗(yàn)==》對(duì)姓名和身份證號(hào)碼進(jìn)行校驗(yàn)
(1)配置
https://www.apispace.com/explore/service
打開網(wǎng)址


首次購(gòu)買有20次的免費(fèi)使用?。?! ,購(gòu)買完如下~

往下滑可以看見主要的代碼

(2)代碼實(shí)現(xiàn)
/**
* 二要素校驗(yàn)
* @param idNumber 身份證
* @param realname 姓名
* @return true則為一致,匹配正確
* @throws IOException
*/
private boolean validateIdCardAndName(String idNumber, String realname) throws IOException {
// 示例:判斷身份證號(hào)和姓名是否匹配
OkHttpClient client = new OkHttpClient();
//校驗(yàn)身份和姓名是否匹配 ==》二要素校驗(yàn)
RequestBody body = RequestBody.create(okhttp3.MediaType.get("application/x-www-form-urlencoded"),
"realname=" + realname + "&idcard=" + idNumber
);
//下面的addHeader和url都可以在上面購(gòu)買完可以看見信息
Request request = new Request.Builder()
.url("換成自己的?。。。。。。。。?!")
.method("POST", body)
.addHeader("X-APISpace-Token", "換成自己的!?。。。。。。。。?)
.build(); // 移除重復(fù)的 Content-Type 頭
Response response = client.newCall(request).execute();
//System.out.println(response.body().string());
//打印出來的{"requestId":"f20067dac6633685bd348f9e388b","data":{"valid":false,"incorrect":101,"message":"不一致"},"code":0,"message":"success"}
if (response.code() != 200) {
return false;
}
if (response.body() == null) {
return false;
}
try {
JSONObject responseJson = JSON.parseObject(response.body().string());
if (responseJson.containsKey("data") && responseJson.getJSONObject("data").containsKey("message")) {
JSONObject dataJson = responseJson.getJSONObject("data");
String dataMessage = dataJson.getString("message");
return "一致".equals(dataMessage);
} else {
System.out.println("響應(yīng)缺少必要字段");
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 獲取姓名
String nameInfo = combined.get("姓名");
JSONObject nameJson = JSON.parseObject(nameInfo);
String realname = nameJson.getString("words");
//校驗(yàn)姓名和身份證是否匹配
boolean validateIdCardAndName = validateIdCardAndName(idNumber, realname);
if (!validateIdCardAndName){
//說明當(dāng)前身份證于當(dāng)前姓名不匹配
return ResponseEntity.badRequest().body("姓名和身份不匹配,請(qǐng)檢查填寫信息是否正確");
}到此這篇關(guān)于springboot實(shí)現(xiàn)調(diào)用百度ocr實(shí)現(xiàn)身份識(shí)別+二要素校驗(yàn)的文章就介紹到這了,更多相關(guān)springboot身份識(shí)別+二要素校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何將任意類型的Object對(duì)象轉(zhuǎn)換為相應(yīng)的實(shí)體對(duì)象
這篇文章主要介紹了Java如何將任意類型的Object對(duì)象轉(zhuǎn)換為相應(yīng)的實(shí)體對(duì)象問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
jmeter如何自動(dòng)生成測(cè)試報(bào)告
這篇文章主要介紹了jmeter如何自動(dòng)生成測(cè)試報(bào)告,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Java如何根據(jù)前端返回的字段名進(jìn)行查詢數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Java如何根據(jù)前端返回的字段名進(jìn)行查詢數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
java項(xiàng)目idea構(gòu)建總是報(bào)內(nèi)存溢出怎么解決詳析
這篇文章主要介紹了java項(xiàng)目idea構(gòu)建總是報(bào)內(nèi)存溢出怎么解決的相關(guān)資料,方法包括增加IDEA內(nèi)存分配、調(diào)整項(xiàng)目編譯設(shè)置、配置Gradle構(gòu)建內(nèi)存、優(yōu)化項(xiàng)目結(jié)構(gòu)、清理不必要的依賴、使用命令行構(gòu)建、更新IDEA和JDK、清理IDEA緩存和禁用不必要的插件,需要的朋友可以參考下2025-03-03
Spring?Boot整合log4j2日志配置的詳細(xì)教程
這篇文章主要介紹了SpringBoot項(xiàng)目中整合Log4j2日志框架的步驟和配置,包括常用日志框架的比較、配置參數(shù)介紹、Log4j2配置詳解以及使用步驟,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02

