添加依赖:
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.3.1
mysql
mysql-connector-java
runtime
com.baidu.aip
java-sdk
4.16.1
io.jsonwebtoken
jjwt
0.9.1
在application.properties
中添加:
baidu.face.appId=APP_ID
baidu.face.apiKey=API_KEY
baidu.face.secretKey=SECRET_KEY
baidu.face.imageType=BASE64
baidu.face.groupId=user_group
package com.example.demo.utils;
import com.baidu.aip.face.AipFace;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
@Component
public class BaiduAiUtils {
@Value("${baidu.face.appId}")
private String APP_ID;
@Value("${baidu.face.apiKey}")
private String API_KEY;
@Value("${baidu.face.secretKey}")
private String SECRET_KEY;
@Value("${baidu.face.imageType}")
private String IMAGE_TYPE;
@Value("${baidu.face.groupId}")
private String GROUP_ID;
private AipFace client;
private HashMap options = new HashMap<>();
@PostConstruct
public void init() {
// 初始化AipFace客户端
client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
// 设置人脸检测参数
options.put("quality_control", "NORMAL"); // 图像质量控制
options.put("liveness_control", "LOW"); // 活体检测等级
}
// 人脸搜索(用于登录)
public String faceSearch(String imageBase64) {
try {
JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);
if (res.getInt("error_code") == 0) {
JSONObject result = res.getJSONObject("result");
if (result.has("user_list")) {
var userList = result.getJSONArray("user_list");
if (userList.length() > 0) {
var user = userList.getJSONObject(0);
double score = user.getDouble("score");
if (score > 80) { // 相似度阈值
return user.getString("user_id");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 人脸注册(用于首次绑定)
public boolean faceRegister(String userId, String imageBase64) {
try {
JSONObject res = client.addUser(imageBase64, IMAGE_TYPE, GROUP_ID, userId, options);
return res.getInt("error_code") == 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
@Component
public class BaiduAiUtils {
@Value("${baidu.face.appId}")
private String APP_ID;
@Value("${baidu.face.apiKey}")
private String API_KEY;
@Value("${baidu.face.secretKey}")
private String SECRET_KEY;
@Value("${baidu.face.imageType}")
private String IMAGE_TYPE;
@Value("${baidu.face.groupId}")
private String GROUP_ID;
private AipFace client;
private HashMap options = new HashMap<>();
@Component
:将此类标记为 Spring 组件,由 Spring 容器管理@Value
:从配置文件读取百度 AI 相关的认证信息和参数AipFace client
:百度人脸识别 API 的客户端options
:API 调用时的可选参数配置APP_ID
、API_KEY
、SECRET_KEY
baidu.face.appId=你的AppID
baidu.face.apiKey=你的API Key
baidu.face.secretKey=你的Secret Key
IMAGE_TYPE
BASE64
:图像数据为 Base64 编码字符串(常用)。URL
:图像数据为网络 URL 地址。FACE_TOKEN
:图像数据为人脸标识(face_token)。baidu.face.imageType=BASE64
GROUP_ID
GROUP_ID
。baidu.face.groupId=users_group_001
AipFace client
@PostConstruct
注解的 init()
方法中完成初始化: java
client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
HashMap options
init()
方法中预配置了两个常用参数: java
options.put("quality_control", "NORMAL"); // 图像质量控制(NORMAL表示中等质量)
options.put("liveness_control", "LOW"); // 活体检测等级(LOW表示低等级检测)
quality_control
:图像质量控制,可选值为 NONE
(不控制)、LOW
(低)、NORMAL
(中)、HIGH
(高)。liveness_control
:活体检测等级,可选值为 NONE
、LOW
、MEDIUM
、HIGH
。max_user_num
:人脸搜索时返回的最大用户数。@PostConstruct
public void init() {
// 初始化AipFace客户端
client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
// 设置人脸检测参数
options.put("quality_control", "NORMAL"); // 图像质量控制
options.put("liveness_control", "LOW"); // 活体检测等级
}
@PostConstruct
:在 Bean 初始化完成后执行此方法quality_control
:控制图像质量,防止模糊或光照不佳的图片liveness_control
:活体检测等级,防止照片 / 视频欺骗public String faceSearch(String imageBase64) {
try {
JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);
if (res.getInt("error_code") == 0) {
JSONObject result = res.getJSONObject("result");
if (result.has("user_list")) {
var userList = result.getJSONArray("user_list");
if (userList.length() > 0) {
var user = userList.getJSONObject(0);
double score = user.getDouble("score");
if (score > 80) { // 相似度阈值
return user.getString("user_id");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String faceSearch(String imageBase64)
功能:在指定用户组(GROUP_ID
)中搜索与输入人脸最相似的用户。
参数:imageBase64
:待搜索的人脸图像的 Base64 编码字符串。
JSONObject res = client.search(imageBase64, IMAGE_TYPE, GROUP_ID, options);
关键参数:
imageBase64
:人脸图像数据。IMAGE_TYPE
:图像类型(如BASE64
)。GROUP_ID
:用户组 ID,指定在哪个用户组中搜索。options
:可选参数(如活体检测、质量控制)。返回值:百度 API 返回的 JSON 结果,包含错误码和匹配结果。
if (res.getInt("error_code") == 0) { ... }
错误码检查:
error_code == 0
表示 API 调用成功。JSONObject result = res.getJSONObject("result");
if (result.has("user_list")) { ... }
结果结构:
result
:API 返回的结果数据。user_list
:匹配到的用户列表(按相似度降序排列)。var userList = result.getJSONArray("user_list");
if (userList.length() > 0) { ... }
var user = userList.getJSONObject(0);
double score = user.getDouble("score");
if (score > 80) { ... }
score
:人脸相似度得分(范围 0-100)。score > 80
:自定义阈值,仅当相似度高于 80 分时才认为匹配成功。catch (Exception e) {
e.printStackTrace();
}
return null;
null
,表示搜索失败。API 成功调用时返回的 JSON 结构示例:
{
"error_code": 0,
"error_msg": "SUCCESS",
"log_id": 4255671843335,
"timestamp": 1695352327,
"cached": 0,
"result": {
"face_token": "6c6a5f5d7a5e5f4b5d3e2c1a0b9c8d",
"user_list": [
{
"group_id": "users_group_001",
"user_id": "user123",
"user_info": "",
"score": 92.5 // 相似度得分
}
]
}
}
public boolean faceRegister(String userId, String imageBase64) {
try {
JSONObject res = client.addUser(imageBase64, IMAGE_TYPE, GROUP_ID, userId, options);
return res.getInt("error_code") == 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
package com.example.demo.service;
import com.example.demo.entity.SysUser;
import com.example.demo.utils.BaiduAiUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FaceLoginService {
@Autowired
private BaiduAiUtils baiduAiUtils;
@Autowired
private UserService userService; // 假设已有用户服务
// 人脸登录验证
public SysUser loginByFace(String imageBase64) {
// 1. 调用百度AI人脸搜索
String userId = baiduAiUtils.faceSearch(imageBase64);
if (userId != null) {
// 2. 查询用户信息
return userService.getUserById(Long.valueOf(userId));
}
return null;
}
// 人脸注册
public boolean registerFace(Long userId, String imageBase64) {
return baiduAiUtils.faceRegister(userId.toString(), imageBase64);
}
}
package com.example.demo.controller;
import com.example.demo.entity.SysUser;
import com.example.demo.service.FaceLoginService;
import com.example.demo.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/face")
public class FaceLoginController {
@Autowired
private FaceLoginService faceLoginService;
@PostMapping("/login")
public Map faceLogin(@RequestBody Map params) {
String imageBase64 = params.get("image");
SysUser user = faceLoginService.loginByFace(imageBase64);
Map result = new HashMap<>();
if (user != null) {
// 生成JWT Token
String token = JwtUtils.generateToken(user.getId());
result.put("code", 200);
result.put("message", "登录成功");
result.put("token", token);
result.put("user", user);
} else {
result.put("code", 401);
result.put("message", "人脸识别失败");
}
return result;
}
@PostMapping("/register")
public Map faceRegister(@RequestBody Map params) {
Long userId = Long.valueOf(params.get("userId"));
String imageBase64 = params.get("image");
boolean success = faceLoginService.registerFace(userId, imageBase64);
return success ?
Map.of("code", 200, "message", "人脸注册成功") :
Map.of("code", 500, "message", "人脸注册失败");
}
}