Просмотр исходного кода

Merge branch 'master' of http://git.zonelife.cn:3001/IT/MicroService

lianshufeng 1 год назад
Родитель
Сommit
4e7f87d7ee

+ 32 - 0
centers/AuthCenter/AuthClient/src/main/java/com/github/microservice/auth/client/content/ResultContent.java

@@ -38,6 +38,9 @@ public class ResultContent<T> {
     @Setter
     private ResultException exception;
 
+    @Getter
+    @Setter
+    private Integer code = 200;
 
     /**
      * 获取内容
@@ -64,4 +67,33 @@ public class ResultContent<T> {
         return build(content == null ? ResultState.Fail : ResultState.Success, content);
     }
 
+    public static <T> ResultContent buildFail(String msg) {
+        return ResultContent.builder().state(ResultState.Fail).code(500).msg(msg).build();
+    }
+
+    public static <T> ResultContent buildFail(String msg, Integer code) {
+        return ResultContent.builder().state(ResultState.Fail).code(code).msg(msg).build();
+    }
+
+    public static <T> ResultContent buildSuccess(String msg) {
+        return build(ResultState.Success, msg);
+    }
+
+    public static <T> ResultContent buildSuccess(T content) {
+        return build(ResultState.Success, content);
+    }
+
+    public static <T> ResultContent buildSuccess() {
+        return build(ResultState.Success, ResultState.Success.getRemark());
+    }
+
+    public boolean isSuccess()
+    {
+        return ResultState.Success.equals(this.state);
+    }
+
+    public boolean isFailed()
+    {
+        return !ResultState.Success.equals(this.state);
+    }
 }

+ 1 - 0
centers/AuthCenter/AuthClient/src/main/java/com/github/microservice/auth/client/content/ResultState.java

@@ -46,6 +46,7 @@ public enum ResultState {
 
     TokenLoginParmError("令牌登陆的参数类型错误 "),
 
+    FaceNotExists("人脸图片不存在")
     ;
 
     @Getter

+ 19 - 0
centers/AuthCenter/AuthClient/src/main/java/com/github/microservice/auth/client/model/UserFaceQueryModel.java

@@ -0,0 +1,19 @@
+package com.github.microservice.auth.client.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Data
+@ToString(callSuper = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode
+@Schema(name = "userFaceQueryModel", description = "查询用户人脸结果模型")
+public class UserFaceQueryModel {
+
+    @Schema(description = "人脸图片文件id")
+    private String faceFileId;
+
+    @Schema(description = "人脸图片Base64")
+    private String userFace;
+}

+ 31 - 0
centers/AuthCenter/AuthClient/src/main/java/com/github/microservice/auth/client/model/UserFaceUploadModel.java

@@ -0,0 +1,31 @@
+package com.github.microservice.auth.client.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+
+import java.util.List;
+
+@Data
+@ToString(callSuper = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode
+@Schema(name = "userFaceUploadModel", description = "人脸上传模型")
+public class UserFaceUploadModel {
+
+    @Schema(description = "用户id")
+    @NotNull(message = "userId不能为null")
+    private String userId;
+
+    @Schema(description = "人脸图片")
+    @NotNull(message = "userFace不能为null")
+    private String userFace;
+
+    @Schema(description = "对比人脸照片")
+    @NotNull(message = "compareFace不能为null")
+    private String compareFace;
+
+    @Schema(description = "更新的图片文件id")
+    private String updateFaceFileId;
+}

+ 35 - 0
centers/AuthCenter/AuthClient/src/main/java/com/github/microservice/auth/client/service/UserFaceService.java

@@ -0,0 +1,35 @@
+package com.github.microservice.auth.client.service;
+
+import com.github.microservice.auth.client.content.ResultContent;
+import com.github.microservice.auth.client.model.UserFaceQueryModel;
+import com.github.microservice.auth.client.model.UserFaceUploadModel;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(name = "authserver/manager/userFace")
+public interface UserFaceService {
+
+    @Operation(summary = "上传用户人脸图片", description = "上传用户人脸图片,用于人脸新增或替换")
+    @RequestMapping(value = "upload", method = RequestMethod.POST)
+    ResultContent<String> upload(@RequestBody @Valid UserFaceUploadModel userFaceUploadModel);
+
+    @Operation(summary = "删除用户人脸图片", description = "删除指定用户人脸图片")
+    @RequestMapping(value = "delete", method = RequestMethod.POST)
+    ResultContent delete(@RequestParam("userId") String userId, @RequestParam("faceFileId") String faceFileId);
+
+    @Operation(summary = "查询用户人脸图片", description = "查询用户人脸图片")
+    @RequestMapping(value = "get", method = RequestMethod.GET)
+    ResultContent<List<UserFaceQueryModel>> get(@RequestParam("userId") String userId);
+
+    @Operation(summary = "比对人脸图片", description = "比对人脸图片")
+    @RequestMapping(value = "matches", method = RequestMethod.POST)
+    ResultContent<String> matches(@RequestParam("userFace") String userFace);
+}

+ 19 - 0
centers/AuthCenter/AuthServer/src/main/java/com/github/microservice/auth/server/core/controller/manager/UserFaceManagerController.java

@@ -0,0 +1,19 @@
+package com.github.microservice.auth.server.core.controller.manager;
+
+import com.github.microservice.auth.client.service.UserFaceService;
+import com.github.microservice.auth.client.service.UserLoginLogService;
+import com.github.microservice.core.delegate.DelegateMapping;
+import lombok.experimental.Delegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("manager/userFace")
+@DelegateMapping(types = UserFaceService.class)
+public class UserFaceManagerController implements UserFaceService {
+
+    @Autowired
+    @Delegate
+    private UserFaceService userFaceService;
+}

+ 13 - 1
centers/AuthCenter/AuthServer/src/main/java/com/github/microservice/auth/server/core/domain/User.java

@@ -1,11 +1,16 @@
 package com.github.microservice.auth.server.core.domain;
 
 import com.github.microservice.components.data.mongo.mongo.domain.SuperEntity;
+import com.mongodb.client.gridfs.model.GridFSFile;
 import lombok.*;
 import org.springframework.data.mongodb.core.index.Indexed;
 import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 import org.springframework.util.Assert;
 
+import java.util.List;
+import java.util.Set;
+
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Builder
@@ -39,6 +44,14 @@ public class User extends SuperEntity {
     @Indexed
     private boolean disable;
 
+    //人脸图片文件id
+    @Indexed
+    private List<String> facePic;
+
+    //NFC卡号
+    @Indexed
+    private List<String> nfcCard;
+
     /**
      * 构建用户
      *
@@ -52,5 +65,4 @@ public class User extends SuperEntity {
         return user;
     }
 
-
 }

+ 213 - 0
centers/AuthCenter/AuthServer/src/main/java/com/github/microservice/auth/server/core/service/local/UserFaceServiceImpl.java

@@ -0,0 +1,213 @@
+package com.github.microservice.auth.server.core.service.local;
+
+import com.github.microservice.auth.client.content.ResultContent;
+import com.github.microservice.auth.client.content.ResultState;
+import com.github.microservice.auth.client.model.UserFaceQueryModel;
+import com.github.microservice.auth.client.model.UserFaceUploadModel;
+import com.github.microservice.auth.client.service.UserFaceService;
+import com.github.microservice.auth.server.core.dao.UserDao;
+import com.github.microservice.auth.server.core.domain.User;
+import com.mongodb.client.gridfs.GridFSFindIterable;
+import com.mongodb.client.gridfs.model.GridFSFile;
+import jakarta.validation.constraints.NotNull;
+import lombok.Cleanup;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.gridfs.GridFsResource;
+import org.springframework.data.mongodb.gridfs.GridFsTemplate;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.List;
+
+@Slf4j
+@Service
+public class UserFaceServiceImpl implements UserFaceService {
+
+    @Autowired
+    UserDao userDao;
+
+    @Autowired
+    GridFsTemplate gridFsTemplate;
+
+    @Autowired
+    RestTemplate restTemplate;
+
+    @Value("${faceImage.width}")
+    private int width;
+
+    @Value("${faceImage.height}")
+    private int height;
+    @Autowired
+    private PasswordEncoder passwordEncoder;
+
+
+    /**
+     * 上传人脸图片
+     *
+     * @param userFaceUploadModel
+     * @return
+     */
+    @SneakyThrows
+    public ResultContent<String> upload(UserFaceUploadModel userFaceUploadModel) {
+        User user = userDao.findTop1ById(userFaceUploadModel.getUserId());
+        if (user == null) {
+            return ResultContent.build(ResultState.UserNotExists);
+        }
+        //TODO 调整图片大小
+        byte[] bytes = imageResizer(userFaceUploadModel.getUserFace());
+        //TODO 上传人脸库,对比成功后入库
+        @Cleanup ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+        String fileId = gridFsTemplate.store(byteArrayInputStream, UUID.randomUUID().toString(),Map.of("userId", userFaceUploadModel.getUserId())).toHexString();
+
+        List<String> facePic = user.getFacePic();
+        if (facePic == null || facePic.isEmpty()) {
+            facePic = new ArrayList<>();
+        }
+        if (StringUtils.isNotBlank(userFaceUploadModel.getUpdateFaceFileId())){
+            //替换原人脸图片
+            if (!facePic.contains(userFaceUploadModel.getUpdateFaceFileId())){
+                return ResultContent.build(ResultState.FaceNotExists);
+            }
+            int index = facePic.indexOf(userFaceUploadModel.getUpdateFaceFileId());
+            facePic.set(index, fileId);
+        }else {
+            facePic.add(fileId);
+        }
+        user.setFacePic(facePic);
+        userDao.save(user);
+        return ResultContent.buildContent(fileId);
+    }
+
+    /**
+     * 删除用户指定人脸图片
+     * @param userId
+     * @param faceFileId
+     * @return
+     */
+    public ResultContent delete(@NotNull String userId, @NotNull String faceFileId) {
+        User user = userDao.findTop1ById(userId);
+        if (user == null) {
+            return ResultContent.build(ResultState.UserNotExists);
+        }
+
+        List<String> facePic = user.getFacePic();
+        if (facePic == null || facePic.isEmpty()) {
+            return ResultContent.build(ResultState.FaceNotExists);
+        }
+
+        if (!facePic.contains(faceFileId)) {
+            return ResultContent.build(ResultState.FaceNotExists);
+        }
+
+        facePic.remove(faceFileId);
+        user.setFacePic(facePic);
+        userDao.save(user);
+        return ResultContent.build(ResultState.Success);
+    }
+
+    /**
+     * 获取用户人脸认证图片
+     * @param userId
+     * @return
+     */
+    @SneakyThrows
+    public ResultContent<List<UserFaceQueryModel>> get(String userId){
+        User user = userDao.findTop1ById(userId);
+        if (user == null) {
+            return ResultContent.build(ResultState.UserNotExists);
+        }
+        //初始化返回结果
+        List<UserFaceQueryModel> userFaceBase64List = new ArrayList<>();
+
+        List<String> facePic = user.getFacePic();
+        if (facePic != null && !facePic.isEmpty()) {
+            Query query = new Query(Criteria.where("_id").in(facePic));
+            GridFSFindIterable gridFSFiles = gridFsTemplate.find(query);
+            for (GridFSFile gridFS : gridFSFiles) {
+                @Cleanup InputStream inputStream = gridFsTemplate.getResource(gridFS).getContent();
+                UserFaceQueryModel userFaceQueryModel = new UserFaceQueryModel();
+                String userFace = convertInputStreamToBase64(inputStream);
+                userFaceQueryModel.setFaceFileId(gridFS.getObjectId().toHexString());
+                userFaceQueryModel.setUserFace(userFace);
+                userFaceBase64List.add(userFaceQueryModel);
+            }
+        }
+        return ResultContent.buildContent(userFaceBase64List);
+    }
+
+    public ResultContent<String> matches(String userFace){
+
+        return ResultContent.buildContent("userId");
+    }
+
+    /**
+     * 将 InputStream 转换为 Base64 字符串
+     *
+     * @param inputStream 输入流
+     * @return Base64 编码的字符串
+     * @throws IOException 如果发生 I/O 错误
+     */
+    @SneakyThrows
+    public static String convertInputStreamToBase64(InputStream inputStream){
+        @Cleanup ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int bytesRead;
+        while ((bytesRead = inputStream.read(buffer)) != -1) {
+            outputStream.write(buffer, 0, bytesRead);
+        }
+        byte[] bytes = outputStream.toByteArray();
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+
+    private byte[] imageResizer(String base64Image){
+        // 解码 Base64 字符串为 BufferedImage
+        BufferedImage originalImage = decodeBase64ToImage(base64Image);
+
+        // 调整图像大小
+        BufferedImage resizedImage = resizeImage(originalImage, width, height);
+
+        // 将调整后的图像转换为字节组
+        return encodeImageToBytes(resizedImage);
+
+    }
+
+    private static BufferedImage resizeImage(BufferedImage originalImage, int width, int height) {
+        BufferedImage resizedImage = new BufferedImage(width, height, originalImage.getType());
+        Graphics2D g = resizedImage.createGraphics();
+        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+        g.drawImage(originalImage, 0, 0, width, height, null);
+        g.dispose();
+
+        return resizedImage;
+    }
+
+    @SneakyThrows
+    private static BufferedImage decodeBase64ToImage(String base64Image) {
+        byte[] imageBytes = Base64.getDecoder().decode(base64Image);
+        @Cleanup ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
+        return ImageIO.read(bais);
+    }
+
+    @SneakyThrows
+    private static byte[] encodeImageToBytes(BufferedImage image) {
+      @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ImageIO.write(image, "png", baos);
+      return baos.toByteArray();
+    }
+}

+ 3 - 1
centers/AuthCenter/AuthServer/src/main/resources/application-dev.yml

@@ -48,7 +48,9 @@ init:
               passWord: xiaoxue
 
 
-
+faceImage:
+  width: 1280
+  height: 720
 
 
 springdoc: