Browse Source

Merge remote-tracking branch 'origin/zy' into lzy

# Conflicts:
#	.idea/dataSources.xml
#	.idea/jarRepositories.xml
#	.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_11.xml
#	.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_11.xml
#	.idea/libraries/Maven__com_alibaba_fastjson_1_2_83.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_core_4_5_10.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_kms_2_11_0.xml
#	.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_ram_3_1_0.xml
#	.idea/libraries/Maven__com_aliyun_oss_aliyun_sdk_oss_3_15_1.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_annotation_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_boot_starter_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_core_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_extension_3_5_4.xml
#	.idea/libraries/Maven__com_baomidou_mybatis_plus_spring_boot_autoconfigure_3_5_4.xml
#	.idea/libraries/Maven__com_fasterxml_classmate_1_5_1.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_13_4_2.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_4.xml
#	.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_13_4.xml
#	.idea/libraries/Maven__com_github_jsqlparser_jsqlparser_4_6.xml
#	.idea/libraries/Maven__com_google_code_gson_gson_2_9_1.xml
#	.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_7_0.xml
#	.idea/libraries/Maven__com_mysql_mysql_connector_j_8_0_31.xml
#	.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
#	.idea/libraries/Maven__com_zaxxer_HikariCP_4_0_3.xml
#	.idea/libraries/Maven__commons_codec_commons_codec_1_15.xml
#	.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml
#	.idea/libraries/Maven__io_jsonwebtoken_jjwt_0_9_0.xml
#	.idea/libraries/Maven__io_lettuce_lettuce_core_6_1_10_RELEASE.xml
#	.idea/libraries/Maven__io_netty_netty_buffer_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_codec_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_common_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_handler_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_resolver_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_transport_4_1_85_Final.xml
#	.idea/libraries/Maven__io_netty_netty_transport_native_unix_common_4_1_85_Final.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_api_0_33_0.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_noop_0_33_0.xml
#	.idea/libraries/Maven__io_opentracing_opentracing_util_0_33_0.xml
#	.idea/libraries/Maven__io_projectreactor_reactor_core_3_4_25.xml
#	.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml
#	.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml
#	.idea/libraries/Maven__jakarta_validation_jakarta_validation_api_2_0_2.xml
#	.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml
#	.idea/libraries/Maven__javax_activation_javax_activation_api_1_2_0.xml
#	.idea/libraries/Maven__javax_validation_validation_api_2_0_1_Final.xml
#	.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_3_1.xml
#	.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_12_19.xml
#	.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_12_19.xml
#	.idea/libraries/Maven__net_minidev_accessors_smart_2_4_8.xml
#	.idea/libraries/Maven__net_minidev_json_smart_2_4_8.xml
#	.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_13.xml
#	.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_15.xml
#	.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_17_2.xml
#	.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_17_2.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_69.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_9_0_69.xml
#	.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_69.xml
#	.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_2.xml
#	.idea/libraries/Maven__org_assertj_assertj_core_3_22_0.xml
#	.idea/libraries/Maven__org_codehaus_jettison_jettison_1_1.xml
#	.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml
#	.idea/libraries/Maven__org_hibernate_validator_hibernate_validator_6_2_0_Final.xml
#	.idea/libraries/Maven__org_ini4j_ini4j_0_5_4.xml
#	.idea/libraries/Maven__org_jacoco_org_jacoco_agent_runtime_0_8_5.xml
#	.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_4_3_Final.xml
#	.idea/libraries/Maven__org_jdom_jdom2_2_0_6_1.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_8_2.xml
#	.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_8_2.xml
#	.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_8_2.xml
#	.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_8_2.xml
#	.idea/libraries/Maven__org_mockito_mockito_core_4_5_1.xml
#	.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_4_5_1.xml
#	.idea/libraries/Maven__org_mybatis_mybatis_3_5_11.xml
#	.idea/libraries/Maven__org_mybatis_mybatis_spring_2_1_1.xml
#	.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_autoconfigure_2_3_0.xml
#	.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_starter_2_3_0.xml
#	.idea/libraries/Maven__org_objenesis_objenesis_3_2.xml
#	.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml
#	.idea/libraries/Maven__org_ow2_asm_asm_9_1.xml
#	.idea/libraries/Maven__org_projectlombok_lombok_1_18_24.xml
#	.idea/libraries/Maven__org_reactivestreams_reactive_streams_1_0_4.xml
#	.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_1.xml
#	.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_36.xml
#	.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_36.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_data_redis_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_commons_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_keyvalue_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_data_spring_data_redis_2_7_6.xml
#	.idea/libraries/Maven__org_springframework_spring_aop_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_beans_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_context_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_context_support_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_core_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_expression_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_jcl_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_jdbc_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_oxm_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_test_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_tx_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_web_5_3_24.xml
#	.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_24.xml
#	.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_9_0.xml
#	.idea/libraries/Maven__org_yaml_snakeyaml_1_30.xml
#	.idea/libraries/Maven__stax_stax_api_1_0_1.xml
#	.idea/misc.xml
#	.idea/mybatisx/templates.xml
#	Marketplace/src/main/java/com/dt/MarketplaceApplication.java
#	Marketplace/src/main/java/com/dt/intercepter/AuthIntercepter.java
lzy 4 days ago
parent
commit
55bc98c19e
28 changed files with 1143 additions and 24 deletions
  1. 8 0
      .idea/.gitignore
  2. 13 0
      .idea/libraries/Maven__org_springframework_security_spring_security_crypto_5_7_6.xml
  3. 1 0
      Marketplace/ArcFace64.dat
  4. BIN
      Marketplace/libs/WIN64/libarcsoft_face.dll
  5. BIN
      Marketplace/libs/WIN64/libarcsoft_face_engine.dll
  6. BIN
      Marketplace/libs/WIN64/libarcsoft_face_engine_jni.dll
  7. BIN
      Marketplace/libs/arcsoft-sdk-face-3.0.0.0.jar
  8. 22 22
      Marketplace/pom.xml
  9. 195 0
      Marketplace/src/main/java/com/dt/FaceEngineTest.java
  10. 0 1
      Marketplace/src/main/java/com/dt/MarketplaceApplication.java
  11. 23 0
      Marketplace/src/main/java/com/dt/config/GlobalExceptionHandler.java
  12. 30 0
      Marketplace/src/main/java/com/dt/config/RedisConfig.java
  13. 3 0
      Marketplace/src/main/java/com/dt/intercepter/AuthIntercepter.java
  14. 0 1
      Marketplace/src/main/java/com/dt/oss/controller/OSSController.java
  15. 72 0
      Marketplace/src/main/java/com/dt/user/controller/UserController.java
  16. 11 0
      Marketplace/src/main/java/com/dt/user/dto/FaceLoginEnableDTO.java
  17. 15 0
      Marketplace/src/main/java/com/dt/user/dto/UserLoginDTO.java
  18. 14 0
      Marketplace/src/main/java/com/dt/user/dto/UserRegisterDTO.java
  19. 20 0
      Marketplace/src/main/java/com/dt/user/mapper/UserMapper.java
  20. 111 0
      Marketplace/src/main/java/com/dt/user/pojo/User.java
  21. 54 0
      Marketplace/src/main/java/com/dt/user/service/UserService.java
  22. 224 0
      Marketplace/src/main/java/com/dt/user/service/impl/UserServiceImpl.java
  23. 13 0
      Marketplace/src/main/java/com/dt/user/vo/UserLoginVO.java
  24. 24 0
      Marketplace/src/main/java/com/dt/util/BCryptPasswordEncoder.java
  25. 165 0
      Marketplace/src/main/java/com/dt/util/FaceEngineUtil.java
  26. 44 0
      Marketplace/src/main/java/com/dt/util/Result.java
  27. 36 0
      Marketplace/src/main/resources/mapper/UserMapper.xml
  28. 45 0
      Marketplace/src/test/java/com/dt/util/FaceEngineUtilTest.java

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 13 - 0
.idea/libraries/Maven__org_springframework_security_spring_security_crypto_5_7_6.xml

@@ -0,0 +1,13 @@
+<component name="libraryTable">
+  <library name="Maven: org.springframework.security:spring-security-crypto:5.7.6">
+    <CLASSES>
+      <root url="jar://D:/apache-maven-3.9.2/MAVEN/org/springframework/security/spring-security-crypto/5.7.6/spring-security-crypto-5.7.6.jar!/" />
+    </CLASSES>
+    <JAVADOC>
+      <root url="jar://D:/apache-maven-3.9.2/MAVEN/org/springframework/security/spring-security-crypto/5.7.6/spring-security-crypto-5.7.6-javadoc.jar!/" />
+    </JAVADOC>
+    <SOURCES>
+      <root url="jar://D:/apache-maven-3.9.2/MAVEN/org/springframework/security/spring-security-crypto/5.7.6/spring-security-crypto-5.7.6-sources.jar!/" />
+    </SOURCES>
+  </library>
+</component>

+ 1 - 0
Marketplace/ArcFace64.dat

@@ -0,0 +1 @@
+EWEPEPEOGMGTELIZJUGECKIUJDBCJTCNISGPBNHLJTJUBHEWGNAKGEGAIOHJDQAJGNCFDRFZJEDMJTICCMGIECEHBWGLHYDSDJJSCSGXHOCCERFADPGEAHJRBVARERCADACUCOHMCBBHIPHFGJCREXGLGFFKJNAWGFHECRCWJJFQEJIXGUBZGIJFAKDTGQBVJNDRGHBDBZJLILFRCOGMJMDOBBGQGNADGKFZJOFZJJBSGHBPGQBNCHABHKFBJTGABSDHGCHXBYCLHPJIHAHRFFDGDHGUHLDGHUJAHNJRESDCADBVBYCQISCRJEECFQCPEBIAHWBTCDGDELHVFYGRBQCLCCFRDTFHALISCYFVIGCFITJRECANIRDUEEDBAUCBDUAZGEJUFBCVFXBWHPHUBTFNJCALBUFTFWAAIBEDGIHRFBGPIQDJFZDDBVAOIVGHFMEGDPCPBVGJAJCLHPARBUDBJNCZAGIPHEDADZGCIFINCUCZGPEKJLDYDAADATIBCOHHEHDOJFGODYESCUEIHJAVDIASBGGTEZFNERHLCNEJGEIGAJDBIYEBAVFEBKCRCFEKDAJRDRJIHVECCPIBIRFEAOJVHMCZCBAOIWGRGVCBHLDNAXJBDEEZDNGADZCPFOEGDCDFJQFMCFGEIAHEDHJABEHCHTARCVHFIODICFBXAYBFDQBFIICYGBASBOFJHJCKGAAXAJJSGPIRDUJRFKAOAYCAGMDHEMBBEVFOHIIBGACEDXATBGEVELAWCZBXCJBKEZHAGNISFNEZHZGZADFVBQJTAFJOAOHJECDGIEFIFUBUDMDOHMHJEWFCBLDAEWIHALELIRASEHFUAAIVGVJUHRBXCDBIDOELEAGGDUBWHNJKBOENEQBRBIDGAXEAHXGQBYANEQCQAPJAERJHJNBPAIGRHAFRDPBTDOINEGAJFHBKJRCKFHFRFMHGHOCUDXFBFOGSACJRCSFUEBGPHBEWCYAVDAFTHFDYDQHUFYHTGQFFHIGMILEYHXFLJIJRFBHYAPBEEIEDECAFAMAMAYJBCTCRHAEBAKJOGWHUAQIDGBCGDQATJEFAENBSETGOHZDODSJTCCEMBNCEJSGSGIGUGVJIDEGWDYAYEMDGCTCIHEEFECCUDEIPDPCJEXBYBXEPEUGIEMCICYHBGWENBGEWDYCRBYAHGMJNGYBGBLCHIM

BIN
Marketplace/libs/WIN64/libarcsoft_face.dll


BIN
Marketplace/libs/WIN64/libarcsoft_face_engine.dll


BIN
Marketplace/libs/WIN64/libarcsoft_face_engine_jni.dll


BIN
Marketplace/libs/arcsoft-sdk-face-3.0.0.0.jar


+ 22 - 22
Marketplace/pom.xml

@@ -30,14 +30,11 @@
             <version>3.5.4</version>
         </dependency>
 
-
         <dependency>
-            <groupId>org.redisson</groupId>
-            <artifactId>redisson-spring-boot-starter</artifactId>
-            <version>3.21.3</version>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
 
-
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
             <artifactId>jjwt</artifactId>
@@ -48,7 +45,13 @@
             <artifactId>fastjson</artifactId>
             <version>1.2.83</version> <!-- 版本可能不同 -->
         </dependency>
-
+        <dependency>
+            <groupId>face</groupId>
+            <artifactId>face</artifactId>
+            <version>3.0.0</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
+        </dependency>
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-boot-starter</artifactId>
@@ -59,22 +62,13 @@
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+        <dependency>
+            <groupId>face</groupId>
+            <artifactId>face</artifactId>
+            <version>3.0.0</version>
+            <scope>system</scope>
+            <systemPath>${project.basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
+        </dependency>
 
 
         <!-- Hibernate Validator (Bean Validation 实现) -->
@@ -122,6 +116,12 @@
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-crypto</artifactId>
+            <version>5.7.6</version>
+        </dependency>
     </dependencies>
     <dependencyManagement>
         <dependencies>

+ 195 - 0
Marketplace/src/main/java/com/dt/FaceEngineTest.java

@@ -0,0 +1,195 @@
+package com.dt;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.*;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.arcsoft.face.toolkit.ImageInfoEx;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FaceEngineTest {
+
+
+    public static void main(String[] args) {
+
+        //从官网获取
+        String appId = "F6mCauSNk86Jn9U21eWbehPHcyVzpNPzrbabLjXwrQds";
+        String sdkKey = "CJgKkF5UDNzWoikdYqBQtFHtbCjeuFCvLJBDnYq7LkFv";
+
+        FaceEngine faceEngine = new FaceEngine(new File("libs/WIN64").getAbsolutePath());
+        //激活引擎
+        int errorCode = faceEngine.activeOnline(appId, sdkKey);
+
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("引擎激活失败");
+        }
+
+        ActiveFileInfo activeFileInfo=new ActiveFileInfo();
+        errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("获取激活文件信息失败");
+        }
+
+        //引擎配置
+        EngineConfiguration engineConfiguration = new EngineConfiguration();
+        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+        engineConfiguration.setDetectFaceMaxNum(10);
+        engineConfiguration.setDetectFaceScaleVal(16);
+        //功能配置
+        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+        functionConfiguration.setSupportAge(true);
+        functionConfiguration.setSupportFace3dAngle(true);
+        functionConfiguration.setSupportFaceDetect(true);
+        functionConfiguration.setSupportFaceRecognition(true);
+        functionConfiguration.setSupportGender(true);
+        functionConfiguration.setSupportLiveness(true);
+        functionConfiguration.setSupportIRLiveness(true);
+        engineConfiguration.setFunctionConfiguration(functionConfiguration);
+
+        //初始化引擎
+        errorCode = faceEngine.init(engineConfiguration);
+
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            System.out.println("初始化引擎失败");
+        }
+
+        String imageUrl1 = "http://127.0.0.1:9005/face/zhang.jpg";
+        String imageUrl2 = "http://127.0.0.1:9005/face/zhang.jpg";
+
+        //人脸检测
+        ImageInfo imageInfo = getImageInfoFromUrl(imageUrl1);
+        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
+        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
+        System.out.println(faceInfoList);
+
+        //特征提取
+        FaceFeature faceFeature = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
+        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
+
+        //人脸检测2
+        ImageInfo imageInfo2 = getImageInfoFromUrl(imageUrl2);
+        List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
+        errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2);
+        System.out.println(faceInfoList2);
+
+        //特征提取2
+        FaceFeature faceFeature2 = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
+        System.out.println("特征值大小:" + faceFeature2.getFeatureData().length);
+
+        //特征比对
+        FaceFeature targetFaceFeature = new FaceFeature();
+        targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
+        FaceFeature sourceFaceFeature = new FaceFeature();
+        sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
+        FaceSimilar faceSimilar = new FaceSimilar();
+
+        errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+
+        System.out.println("相似度:" + faceSimilar.getScore());
+
+        //设置活体测试
+        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
+        //人脸属性检测
+        FunctionConfiguration configuration = new FunctionConfiguration();
+        configuration.setSupportAge(true);
+        configuration.setSupportFace3dAngle(true);
+        configuration.setSupportGender(true);
+        configuration.setSupportLiveness(true);
+        errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
+
+        //性别检测
+        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
+        errorCode = faceEngine.getGender(genderInfoList);
+        System.out.println("性别:" + genderInfoList.get(0).getGender());
+
+        //年龄检测
+        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
+        errorCode = faceEngine.getAge(ageInfoList);
+        System.out.println("年龄:" + ageInfoList.get(0).getAge());
+
+        //3D信息检测
+        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
+        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
+        System.out.println("3D角度:" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
+
+        //活体检测
+        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
+        errorCode = faceEngine.getLiveness(livenessInfoList);
+        System.out.println("活体:" + livenessInfoList.get(0).getLiveness());
+
+        //IR属性处理
+        try {
+            // 获取灰度图像数据
+            URL url = new URL(imageUrl2);
+            BufferedImage bufferedImage = ImageIO.read(url);
+            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "jpg", baos);
+            byte[] imageData = baos.toByteArray();
+            ImageInfo imageInfoGray = ImageFactory.getGrayData(imageData);
+            
+            List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
+            errorCode = faceEngine.detectFaces(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray);
+
+            FunctionConfiguration configuration2 = new FunctionConfiguration();
+            configuration2.setSupportIRLiveness(true);
+            errorCode = faceEngine.processIr(imageInfoGray.getImageData(), imageInfoGray.getWidth(), imageInfoGray.getHeight(), imageInfoGray.getImageFormat(), faceInfoListGray, configuration2);
+            //IR活体检测
+            List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
+            errorCode = faceEngine.getLivenessIr(irLivenessInfo);
+            System.out.println("IR活体:" + irLivenessInfo.get(0).getLiveness());
+        } catch (Exception e) {
+            System.out.println("处理IR图像时发生错误:" + e.getMessage());
+            e.printStackTrace();
+        }
+
+        ImageInfoEx imageInfoEx = new ImageInfoEx();
+        imageInfoEx.setHeight(imageInfo.getHeight());
+        imageInfoEx.setWidth(imageInfo.getWidth());
+        imageInfoEx.setImageFormat(imageInfo.getImageFormat());
+        imageInfoEx.setImageDataPlanes(new byte[][]{imageInfo.getImageData()});
+        imageInfoEx.setImageStrides(new int[]{imageInfo.getWidth() * 3});
+        List<FaceInfo> faceInfoList1 = new ArrayList<>();
+        errorCode = faceEngine.detectFaces(imageInfoEx, DetectModel.ASF_DETECT_MODEL_RGB, faceInfoList1);
+
+        FunctionConfiguration fun = new FunctionConfiguration();
+        fun.setSupportAge(true);
+        errorCode = faceEngine.process(imageInfoEx, faceInfoList1, functionConfiguration);
+        List<AgeInfo> ageInfoList1 = new ArrayList<>();
+        int age = faceEngine.getAge(ageInfoList1);
+        System.out.println("年龄:" + ageInfoList1.get(0).getAge());
+
+        FaceFeature feature = new FaceFeature();
+        errorCode = faceEngine.extractFaceFeature(imageInfoEx, faceInfoList1.get(0), feature);
+
+        //引擎卸载
+        errorCode = faceEngine.unInit();
+    }
+
+    // 从URL获取ImageInfo的方法
+    private static ImageInfo getImageInfoFromUrl(String imageUrl) {
+        try {
+            URL url = new URL(imageUrl);
+            BufferedImage bufferedImage = ImageIO.read(url);
+            
+            // 将BufferedImage转换为byte数组
+            java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "jpg", baos);
+            byte[] imageData = baos.toByteArray();
+            
+            // 使用byte数组创建ImageInfo
+            return ImageFactory.getRGBData(imageData);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

+ 0 - 1
Marketplace/src/main/java/com/dt/MarketplaceApplication.java

@@ -1,6 +1,5 @@
 package com.dt;
 
-import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 

+ 23 - 0
Marketplace/src/main/java/com/dt/config/GlobalExceptionHandler.java

@@ -0,0 +1,23 @@
+//package com.dt.config;
+//
+//import com.dt.util.Result;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.web.bind.annotation.ExceptionHandler;
+//import org.springframework.web.bind.annotation.RestControllerAdvice;
+//
+//@Slf4j
+//@RestControllerAdvice
+//public class GlobalExceptionHandler {
+//
+//    @ExceptionHandler(Exception.class)
+//    public Result handleException(Exception e) {
+//        log.error("系统异常", e);
+//        return new Result(false, "系统异常:" + e.getMessage());
+//    }
+//
+//    @ExceptionHandler(ApiException.class)
+//    public Result handleApiException(ApiException e) {
+//        log.error("业务异常", e);
+//        return new Result(false, e.getMsg());
+//    }
+//}

+ 30 - 0
Marketplace/src/main/java/com/dt/config/RedisConfig.java

@@ -0,0 +1,30 @@
+package com.dt.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.GenericToStringSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        StringRedisTemplate template = new StringRedisTemplate();
+        template.setConnectionFactory(redisConnectionFactory);
+        
+        // 设置key的序列化方式
+        template.setKeySerializer(new GenericToStringSerializer<>(Object.class));
+        template.setHashKeySerializer(new GenericToStringSerializer<>(Object.class));
+        
+        // 设置value的序列化方式
+        template.setValueSerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new StringRedisSerializer());
+        
+        template.afterPropertiesSet();
+        return template;
+    }
+} 

+ 3 - 0
Marketplace/src/main/java/com/dt/intercepter/AuthIntercepter.java

@@ -1,6 +1,7 @@
 package com.dt.intercepter;
 
 
+
 import com.dt.config.ApiException;
 import com.dt.config.CommonContants;
 import com.dt.config.NonLoginRequired;
@@ -31,11 +32,13 @@ public class AuthIntercepter implements HandlerInterceptor {
 
     public AuthIntercepter() {
 
+
     }
 
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handle)
     {
         String token  = request.getHeader(Token);
+
         String requestURI = request.getRequestURI();
         System.err.println(requestURI);
         if (requestURI.equals("/user/login")){

+ 0 - 1
Marketplace/src/main/java/com/dt/oss/controller/OSSController.java

@@ -2,7 +2,6 @@ package com.dt.oss.controller;
 
 import com.dt.config.NonLoginRequired;
 import com.dt.oss.OSSService;
-import com.sun.istack.internal.NotNull;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestPart;

+ 72 - 0
Marketplace/src/main/java/com/dt/user/controller/UserController.java

@@ -0,0 +1,72 @@
+package com.dt.user.controller;
+
+import com.dt.config.NonLoginRequired;
+import com.dt.user.dto.UserLoginDTO;
+import com.dt.user.dto.UserRegisterDTO;
+import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.service.UserService;
+import com.dt.user.vo.UserLoginVO;
+import com.dt.util.Result;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@RequestMapping("/user")
+public class UserController {
+
+    @Autowired
+    private UserService userService;
+    @Autowired
+    private HttpServletRequest request;
+    /**
+     * 登录
+     * @param loginDTO
+     * @return
+     */
+    @PostMapping("/login")
+    @NonLoginRequired
+    public Result login(@Validated @RequestBody UserLoginDTO loginDTO) {
+        UserLoginVO loginVO = userService.login(loginDTO);
+        return new Result(true, "登录成功", loginVO);
+    }
+    /**
+     * 注册
+     * @param registerDTO
+     * @return
+     */
+    @PostMapping("/register")
+    @NonLoginRequired
+    public Result register(@Validated @RequestBody UserRegisterDTO registerDTO) {
+        userService.register(registerDTO);
+        return new Result(true, "注册成功");
+    }
+
+    /**
+     * 人脸登录
+     * @param imageUrl2
+     * @return
+     */
+    @PostMapping("/faceLogin")
+    @NonLoginRequired
+    public Result faceLogin(@RequestParam("imageUrl2") MultipartFile imageUrl2) {
+
+      return   userService.faceLogin( imageUrl2);
+    }
+    /**
+     * 开启人脸识别功能
+     */
+    @PostMapping("/enableFaceLogin")
+    public Result enableFaceLogin(@Validated @RequestBody FaceLoginEnableDTO enableDTO) {
+        return userService.enableFaceLogin(enableDTO,request);
+    }
+    /**
+     * 上传人脸识别图片
+     */
+    @PostMapping("/uploadFaceImage")
+    public Result uploadFaceImage(@RequestParam("faceImage") MultipartFile faceImage) {
+        return userService.uploadFaceImage(faceImage, request);
+    }
+}

+ 11 - 0
Marketplace/src/main/java/com/dt/user/dto/FaceLoginEnableDTO.java

@@ -0,0 +1,11 @@
+package com.dt.user.dto;
+
+import lombok.Data;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FaceLoginEnableDTO {
+    
+    @NotNull(message = "启用状态不能为空")
+    private Integer enabled; // 0-禁用, 1-启用
+} 

+ 15 - 0
Marketplace/src/main/java/com/dt/user/dto/UserLoginDTO.java

@@ -0,0 +1,15 @@
+package com.dt.user.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class UserLoginDTO {
+    
+    @NotBlank(message = "用户名不能为空")
+    private String username;
+    
+    @NotBlank(message = "密码不能为空")
+    private String password;
+} 

+ 14 - 0
Marketplace/src/main/java/com/dt/user/dto/UserRegisterDTO.java

@@ -0,0 +1,14 @@
+package com.dt.user.dto;
+
+import lombok.Data;
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class UserRegisterDTO {
+    
+    @NotBlank(message = "用户名不能为空")
+    private String username;
+    
+    @NotBlank(message = "密码不能为空")
+    private String password;
+} 

+ 20 - 0
Marketplace/src/main/java/com/dt/user/mapper/UserMapper.java

@@ -0,0 +1,20 @@
+package com.dt.user.mapper;
+
+import com.dt.user.pojo.User;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+* @author 张大宇
+* @description 针对表【user(用户表)】的数据库操作Mapper
+* @createDate 2025-07-01 15:03:44
+* @Entity com.dt.user.pojo.User
+*/
+@Mapper
+public interface UserMapper extends BaseMapper<User> {
+
+}
+
+
+
+

+ 111 - 0
Marketplace/src/main/java/com/dt/user/pojo/User.java

@@ -0,0 +1,111 @@
+package com.dt.user.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 用户表
+ * @TableName user
+ */
+@TableName(value ="user")
+@Data
+public class User implements Serializable {
+    /**
+     * 用户ID
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 密码(BCrypt加密)
+     */
+    private String password;
+
+    /**
+     * 真实姓名
+     */
+    private String realName;
+
+    /**
+     * 手机号
+     */
+    private String phone;
+
+    /**
+     * 邮箱
+     */
+    private String email;
+
+    /**
+     * 头像URL
+     */
+    private String avatar;
+
+    /**
+     * 性别(0-未知,1-男,2-女)
+     */
+    private Integer gender;
+
+    /**
+     * 出生日期
+     */
+    private Date birthDate;
+
+    /**
+     * 状态(0-禁用,1-正常)
+     */
+    private Integer status;
+
+    /**
+     * 最后登录时间
+     */
+    private Date lastLoginTime;
+
+    /**
+     * 最后登录IP
+     */
+    private String lastLoginIp;
+
+    /**
+     * 最后登录设备
+     */
+    private String lastLoginDevice;
+
+    /**
+     * 人脸图片URL
+     */
+    private String faceImageUrl;
+
+    /**
+     * 是否启用人脸登录(0-禁用,1-启用)
+     */
+    private Integer faceLoginEnabled;
+
+    /**
+     * 创建时间
+     */
+    private Date createdAt;
+
+    /**
+     * 更新时间
+     */
+    private Date updatedAt;
+
+    /**
+     * 是否删除(0-未删除,1-已删除)
+     */
+    private Integer deleted;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 54 - 0
Marketplace/src/main/java/com/dt/user/service/UserService.java

@@ -0,0 +1,54 @@
+package com.dt.user.service;
+
+import com.dt.user.pojo.User;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.dt.user.dto.UserLoginDTO;
+import com.dt.user.dto.UserRegisterDTO;
+import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.vo.UserLoginVO;
+import com.dt.util.Result;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+* @author 张大宇
+* @description 针对表【user(用户表)】的数据库操作Service
+* @createDate 2025-07-01 15:03:44
+*/
+public interface UserService extends IService<User> {
+    
+    /**
+     * 用户登录
+     * @param loginDTO 登录参数
+     * @return 登录结果
+     */
+    UserLoginVO login(UserLoginDTO loginDTO);
+    
+    /**
+     * 用户注册
+     * @param registerDTO 注册参数
+     */
+    void register(UserRegisterDTO registerDTO);
+
+    /**
+     * 人脸识别登录
+     * @param imageUrl2
+     * @return
+     */
+    Result faceLogin(MultipartFile imageUrl2);
+
+    /**
+     * 开启/关闭人脸识别功能
+     * @param enableDTO 启用参数
+     * @return 操作结果
+     */
+    Result enableFaceLogin(FaceLoginEnableDTO enableDTO, HttpServletRequest request);
+
+    /**
+     * 上传人脸识别图片
+     * @param faceImage 人脸图片
+     * @return 操作结果
+     */
+    Result uploadFaceImage(MultipartFile faceImage, HttpServletRequest request);
+}

+ 224 - 0
Marketplace/src/main/java/com/dt/user/service/impl/UserServiceImpl.java

@@ -0,0 +1,224 @@
+package com.dt.user.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.dt.config.ApiException;
+import com.dt.config.CommonContants;
+import com.dt.oss.OSSService;
+import com.dt.user.dto.UserLoginDTO;
+import com.dt.user.dto.UserRegisterDTO;
+import com.dt.user.dto.FaceLoginEnableDTO;
+import com.dt.user.mapper.UserMapper;
+import com.dt.user.pojo.User;
+import com.dt.user.service.UserService;
+import com.dt.user.vo.UserLoginVO;
+import com.dt.util.BCryptPasswordEncoder;
+import com.dt.util.FaceEngineUtil;
+import com.dt.util.Result;
+import com.dt.util.TokenUtils;
+import org.apache.coyote.Request;
+import org.apache.http.HttpRequest;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author 张大宇
+* @description 针对表【user(用户表)】的数据库操作Service实现
+* @createDate 2025-07-01 15:03:44
+*/
+@Service
+public class UserServiceImpl extends ServiceImpl<UserMapper, User>
+    implements UserService{
+
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private OSSService ossService;
+    @Autowired
+    private HttpServletRequest request;
+    @Override
+    public UserLoginVO login(UserLoginDTO loginDTO) {
+        // 1. 根据用户名查询用户
+        User user = this.getOne(new LambdaQueryWrapper<User>()
+                .eq(User::getUsername, loginDTO.getUsername()));
+        
+        if (user == null) {
+            throw new ApiException(101, "用户名或密码错误");
+        }
+
+        // 2. 校验密码
+        if (!BCryptPasswordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
+            throw new ApiException(101, "用户名或密码错误");
+        }
+
+        // 3. 检查用户状态
+        if (user.getStatus() != null && user.getStatus() == 0) {
+            throw new ApiException(101, "账号已被禁用");
+        }
+
+        // 4. 更新登录信息
+        user.setLastLoginTime(new Date());
+        this.updateById(user);
+
+        // 5. 生成token
+        String token = TokenUtils.createJwtToken(user.getId().toString());
+
+        // 6. 存入Redis
+        stringRedisTemplate.opsForValue().set(user.getId().toString(), token);
+        // 7. 构建返回对象
+        UserLoginVO loginVO = new UserLoginVO();
+        BeanUtils.copyProperties(user, loginVO);
+        loginVO.setToken(token);
+        return loginVO;
+    }
+
+    @Override
+    public void register(UserRegisterDTO registerDTO) {
+        // 1. 检查用户名是否已存在
+        if (this.count(new LambdaQueryWrapper<User>()
+                .eq(User::getUsername, registerDTO.getUsername())) > 0) {
+            throw new ApiException(101, "用户名已存在");
+        }
+
+        // 2. 创建用户对象
+        User user = new User();
+        user.setUsername(registerDTO.getUsername());
+        user.setPassword(BCryptPasswordEncoder.encode(registerDTO.getPassword()));
+
+        // 3. 设置默认值
+        user.setStatus(1); // 正常状态
+        user.setGender(0); // 性别未知
+        user.setCreatedAt(new Date());
+        user.setUpdatedAt(new Date());
+        user.setDeleted(0); // 未删除
+
+        // 4. 保存用户
+        this.save(user);
+    }
+
+    @Override
+    public Result enableFaceLogin(FaceLoginEnableDTO enableDTO, HttpServletRequest request) {
+        try {
+            // 获取当前登录用户ID
+            String token = request.getHeader("token");
+            if (token == null){
+                return new Result(false, "用户未登录");
+            }
+            Long userId = TokenUtils.getUserId(token);
+            // 获取用户信息
+            User user = this.getById(userId);
+            if (user == null) {
+                return new Result(false, "用户不存在");
+            }
+            // 检查用户是否已启用人脸识别功能
+            if (user.getFaceLoginEnabled() == 1) {
+                user.setFaceLoginEnabled(0);
+                user.setUpdatedAt(new Date());
+                this.updateById(user);
+                return new Result(true, "人脸识别功能已关闭");
+            }
+            // 更新人脸识别状态
+            user.setFaceLoginEnabled(enableDTO.getEnabled());
+            user.setUpdatedAt(new Date());
+            this.updateById(user);
+
+            return new Result(true,"人脸识别功能已开启");
+        }catch (Exception e){
+            e.printStackTrace();
+            return new Result(false, "人脸登录失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public Result uploadFaceImage(MultipartFile faceImage, HttpServletRequest request) {
+        try {
+            // 获取当前登录用户ID
+            String token = request.getHeader("token");
+            Long userId = TokenUtils.getUserId(token);
+            if (userId == null) {
+                return new Result(false, "用户未登录");
+            }
+            // 获取用户信息
+            User user = this.getById(userId);
+            if (user == null) {
+                return new Result(false, "用户不存在");
+            }
+            // 上传图片到OSS
+            String imageUrl = ossService.upload(faceImage);
+            // 更新用户人脸图片URL
+            user.setFaceImageUrl(imageUrl);
+            user.setUpdatedAt(new Date());
+            this.updateById(user);
+
+            return new Result(true, "人脸图片上传成功", imageUrl);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new Result(false, "人脸图片上传失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public Result faceLogin(MultipartFile imageUrl2) {
+        try {
+            // 查询所有启用了人脸登录的用户
+            List<User> users = this.list(new LambdaQueryWrapper<User>()
+                    .eq(User::getFaceLoginEnabled, 1)
+                    .isNotNull(User::getFaceImageUrl)
+                    .ne(User::getFaceImageUrl, ""));
+
+            User matchedUser = null;
+            float highestSimilarity = 0f;
+            // 遍历所有用户进行人脸比对
+            for (User user : users) {
+                String storedFaceImage = user.getFaceImageUrl();
+                try {
+                    float similarity = FaceEngineUtil.faceAnalysis(storedFaceImage, imageUrl2);
+                    if (similarity > highestSimilarity) {
+                        highestSimilarity = similarity;
+                        matchedUser = user;
+                    }
+                } catch (Exception e) {
+                  e.printStackTrace();
+                }
+            }
+
+            // 检查是否找到匹配的用户且相似度大于0.8
+            if (matchedUser == null || highestSimilarity < 0.8) {
+                return new Result(false, "人脸识别失败:未找到匹配的用户");
+            }
+
+            // 生成token
+            String token = TokenUtils.createJwtToken(matchedUser.getId().toString());
+
+            // 存入Redis
+            stringRedisTemplate.opsForValue().set(matchedUser.getId().toString(), token);
+
+            // 更新最后登录时间
+            matchedUser.setLastLoginTime(new Date());
+            this.updateById(matchedUser);
+
+            // 构建返回对象
+            UserLoginVO loginVO = new UserLoginVO();
+            BeanUtils.copyProperties(matchedUser, loginVO);
+            loginVO.setToken(token);
+            
+            return new Result(true, "人脸识别登录成功", loginVO);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return new Result(false, "人脸识别失败:" + e.getMessage());
+        }
+    }
+}
+
+
+
+

+ 13 - 0
Marketplace/src/main/java/com/dt/user/vo/UserLoginVO.java

@@ -0,0 +1,13 @@
+package com.dt.user.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class UserLoginVO {
+    
+    private Long id;
+    private String username;
+    private String token;
+} 

+ 24 - 0
Marketplace/src/main/java/com/dt/util/BCryptPasswordEncoder.java

@@ -0,0 +1,24 @@
+package com.dt.util;
+
+import org.springframework.security.crypto.bcrypt.BCrypt;
+
+public class BCryptPasswordEncoder {
+    
+    /**
+     * 加密密码
+     */
+    public static String encode(String password) {
+        return BCrypt.hashpw(password, BCrypt.gensalt());
+    }
+    
+    /**
+     * 验证密码
+     */
+    public static boolean matches(String password, String encodedPassword) {
+        try {
+            return BCrypt.checkpw(password, encodedPassword);
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
+} 

+ 165 - 0
Marketplace/src/main/java/com/dt/util/FaceEngineUtil.java

@@ -0,0 +1,165 @@
+package com.dt.util;
+
+import com.arcsoft.face.*;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectModel;
+import com.arcsoft.face.enums.DetectOrient;
+import com.arcsoft.face.enums.ErrorInfo;
+import com.arcsoft.face.toolkit.ImageFactory;
+import com.arcsoft.face.toolkit.ImageInfo;
+import com.arcsoft.face.toolkit.ImageInfoEx;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class FaceEngineUtil {
+
+    private static final String APP_ID = "F6mCauSNk86Jn9U21eWbehPHcyVzpNPzrbabLjXwrQds";
+    private static final String SDK_KEY = "CJgKkF5UDNzWoikdYqBQtFHtbCjeuFCvLJBDnYq7LkFv";
+    private static final String ENGINE_PATH = new File("libs/WIN64").getAbsolutePath();
+
+    public static float faceAnalysis(String imageUrl1, MultipartFile imageUrl2) {
+        FaceEngine faceEngine = new FaceEngine(ENGINE_PATH);
+        float similarity = 0.0f;
+        // 激活引擎
+        int errorCode = faceEngine.activeOnline(APP_ID, SDK_KEY);
+
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("引擎激活失败");
+            return similarity;
+        }
+
+        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
+        errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
+        if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
+            System.out.println("获取激活文件信息失败");
+            return similarity;
+        }
+
+        // 引擎配置
+        EngineConfiguration engineConfiguration = new EngineConfiguration();
+        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+        engineConfiguration.setDetectFaceMaxNum(10);
+        engineConfiguration.setDetectFaceScaleVal(16);
+        // 功能配置
+        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
+        functionConfiguration.setSupportAge(true);
+        functionConfiguration.setSupportFace3dAngle(true);
+        functionConfiguration.setSupportFaceDetect(true);
+        functionConfiguration.setSupportFaceRecognition(true);
+        functionConfiguration.setSupportGender(true);
+        functionConfiguration.setSupportLiveness(true);
+        functionConfiguration.setSupportIRLiveness(true);
+        engineConfiguration.setFunctionConfiguration(functionConfiguration);
+
+        // 初始化引擎
+        errorCode = faceEngine.init(engineConfiguration);
+
+        if (errorCode != ErrorInfo.MOK.getValue()) {
+            System.out.println("初始化引擎失败");
+            return similarity;
+        }
+
+        try {
+            // 人脸检测
+            ImageInfo imageInfo = getImageInfoFromUrl(imageUrl1);
+            List<FaceInfo> faceInfoList = new ArrayList<>();
+            errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
+            if (faceInfoList.isEmpty()) {
+                System.out.println("未检测到人脸1");
+                return similarity;
+            }
+
+            // 特征提取
+            FaceFeature faceFeature = new FaceFeature();
+            errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
+
+            // 人脸检测2
+            ImageInfo imageInfo2 = getImageInfoFromMultipartFile(imageUrl2);
+            List<FaceInfo> faceInfoList2 = new ArrayList<>();
+            errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2);
+            if (faceInfoList2.isEmpty()) {
+                System.out.println("未检测到人脸2");
+                return similarity;
+            }
+
+            // 特征提取2
+            FaceFeature faceFeature2 = new FaceFeature();
+            errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
+
+            // 特征比对
+            FaceFeature targetFaceFeature = new FaceFeature();
+            targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
+            FaceFeature sourceFaceFeature = new FaceFeature();
+            sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
+            FaceSimilar faceSimilar = new FaceSimilar();
+
+            errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+            similarity = faceSimilar.getScore();
+            System.out.println("相似度:" + similarity);
+
+            return similarity;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return similarity;
+        } finally {
+            // 释放引擎
+            if (faceEngine != null) {
+                faceEngine.unInit();
+            }
+        }
+    }
+
+    private static ImageInfo getImageInfoFromUrl(String imageUrl) {
+        try {
+            URL url = new URL(imageUrl);
+            BufferedImage bufferedImage = ImageIO.read(url);
+
+            // 将BufferedImage转换为byte数组
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "jpg", baos);
+            byte[] imageData = baos.toByteArray();
+
+            // 使用byte数组创建ImageInfo
+            return ImageFactory.getRGBData(imageData);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private static ImageInfo getImageInfoFromMultipartFile(MultipartFile file) {
+        try {
+            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "jpg", baos);
+            byte[] imageData = baos.toByteArray();
+            return ImageFactory.getRGBData(imageData);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private static ImageInfo getGrayImageInfoFromMultipartFile(MultipartFile file) {
+        try {
+            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, "jpg", baos);
+            byte[] imageData = baos.toByteArray();
+            return ImageFactory.getGrayData(imageData);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

+ 44 - 0
Marketplace/src/main/java/com/dt/util/Result.java

@@ -0,0 +1,44 @@
+package com.dt.util;
+
+import java.io.Serializable;
+
+/**
+ * 封装返回结果
+ */
+public class Result implements Serializable{
+    private boolean flag;//执行结果,true为执行成功 false为执行失败
+    private String message;//返回结果信息
+    private Object data;//返回数据
+    public Result(boolean flag, String message) {
+        super();
+        this.flag = flag;
+        this.message = message;
+    }
+
+    public Result(boolean flag, String message, Object data) {
+        this.flag = flag;
+        this.message = message;
+        this.data = data;
+    }
+
+    public boolean isFlag() {
+        return flag;
+    }
+    public void setFlag(boolean flag) {
+        this.flag = flag;
+    }
+    public String getMessage() {
+        return message;
+    }
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(Object data) {
+        this.data = data;
+    }
+}

+ 36 - 0
Marketplace/src/main/resources/mapper/UserMapper.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.dt.user.mapper.UserMapper">
+
+    <resultMap id="BaseResultMap" type="com.dt.user.pojo.User">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="username" column="username" jdbcType="VARCHAR"/>
+            <result property="password" column="password" jdbcType="VARCHAR"/>
+            <result property="realName" column="real_name" jdbcType="VARCHAR"/>
+            <result property="phone" column="phone" jdbcType="VARCHAR"/>
+            <result property="email" column="email" jdbcType="VARCHAR"/>
+            <result property="avatar" column="avatar" jdbcType="VARCHAR"/>
+            <result property="gender" column="gender" jdbcType="TINYINT"/>
+            <result property="birthDate" column="birth_date" jdbcType="DATE"/>
+            <result property="status" column="status" jdbcType="TINYINT"/>
+            <result property="lastLoginTime" column="last_login_time" jdbcType="TIMESTAMP"/>
+            <result property="lastLoginIp" column="last_login_ip" jdbcType="VARCHAR"/>
+            <result property="lastLoginDevice" column="last_login_device" jdbcType="VARCHAR"/>
+            <result property="faceImageUrl" column="face_image_url" jdbcType="VARCHAR"/>
+            <result property="faceLoginEnabled" column="face_login_enabled" jdbcType="TINYINT"/>
+            <result property="createdAt" column="created_at" jdbcType="TIMESTAMP"/>
+            <result property="updatedAt" column="updated_at" jdbcType="TIMESTAMP"/>
+            <result property="deleted" column="deleted" jdbcType="TINYINT"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,username,password,
+        real_name,phone,email,
+        avatar,gender,birth_date,
+        status,last_login_time,last_login_ip,
+        last_login_device,face_image_url,face_login_enabled,
+        created_at,updated_at,deleted
+    </sql>
+</mapper>

+ 45 - 0
Marketplace/src/test/java/com/dt/util/FaceEngineUtilTest.java

@@ -0,0 +1,45 @@
+package com.dt.util;
+
+import com.arcsoft.face.EngineConfiguration;
+import com.arcsoft.face.FaceEngine;
+import com.arcsoft.face.enums.DetectMode;
+import com.arcsoft.face.enums.DetectOrient;
+import com.arcsoft.face.enums.ErrorInfo;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.File;
+
+public class FaceEngineUtilTest {
+
+    @Test
+    public void testFaceEngineInitialization() {
+        String projectRoot = new File("").getAbsolutePath();
+        String enginePath = new File(projectRoot, "libs/WIN64").getAbsolutePath();
+        
+        System.out.println("Engine path: " + enginePath);
+        System.out.println("Files in directory:");
+        File dir = new File(enginePath);
+        if (dir.exists() && dir.isDirectory()) {
+            for (File file : dir.listFiles()) {
+                System.out.println(" - " + file.getName() + " (exists: " + file.exists() + ", readable: " + file.canRead() + ")");
+            }
+        }
+
+        FaceEngine faceEngine = new FaceEngine(enginePath);
+        
+        // Try to initialize the engine
+        EngineConfiguration engineConfiguration = new EngineConfiguration();
+        engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
+        engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
+        engineConfiguration.setDetectFaceMaxNum(10);
+        engineConfiguration.setDetectFaceScaleVal(16);
+        
+        int errorCode = faceEngine.init(engineConfiguration);
+        assertEquals(ErrorInfo.MOK.getValue(), errorCode, "Face engine initialization failed");
+        
+        // Clean up
+        errorCode = faceEngine.unInit();
+        assertEquals(ErrorInfo.MOK.getValue(), errorCode, "Face engine uninitialization failed");
+    }
+}