mirror of
https://github.com/jumpserver/jumpserver.git
synced 2026-01-29 21:51:31 +00:00
feat: 增加人脸识别功能
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import base64
|
||||
import struct
|
||||
import uuid
|
||||
|
||||
import math
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractUser, UserManager as _UserManager
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.shortcuts import reverse
|
||||
from django.utils import timezone
|
||||
@@ -23,13 +27,15 @@ from ._json import JSONFilterMixin
|
||||
from ._role import RoleMixin, SystemRoleManager, OrgRoleManager
|
||||
from ._source import SourceMixin, Source
|
||||
from ._token import TokenMixin
|
||||
from ._face import FaceMixin
|
||||
|
||||
logger = get_logger(__file__)
|
||||
__all__ = [
|
||||
"User",
|
||||
"UserPasswordHistory",
|
||||
"MFAMixin",
|
||||
"AuthMixin"
|
||||
"AuthMixin",
|
||||
"FaceMixin"
|
||||
]
|
||||
|
||||
|
||||
@@ -48,6 +54,7 @@ class User(
|
||||
TokenMixin,
|
||||
RoleMixin,
|
||||
MFAMixin,
|
||||
FaceMixin,
|
||||
LabeledMixin,
|
||||
JSONFilterMixin,
|
||||
AbstractUser,
|
||||
@@ -133,6 +140,9 @@ class User(
|
||||
slack_id = models.CharField(
|
||||
null=True, default=None, max_length=128, verbose_name=_("Slack")
|
||||
)
|
||||
face_vector = fields.EncryptTextField(
|
||||
null=True, blank=True, max_length=2048, verbose_name=_("Face Vector")
|
||||
)
|
||||
date_api_key_last_used = models.DateTimeField(
|
||||
null=True, blank=True, verbose_name=_("Date api key used")
|
||||
)
|
||||
|
||||
56
apps/users/models/user/_face.py
Normal file
56
apps/users/models/user/_face.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import base64
|
||||
import struct
|
||||
|
||||
import math
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from common.utils import (
|
||||
get_logger,
|
||||
)
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class FaceMixin:
|
||||
face_vector = None
|
||||
|
||||
def get_face_vector(self) -> list[float]:
|
||||
if not self.face_vector:
|
||||
raise ValidationError("Face vector is not set.")
|
||||
return self._decode_base64_vector(str(self.face_vector))
|
||||
|
||||
def check_face(self, code) -> bool:
|
||||
distance = self.compare_euclidean_distance(code)
|
||||
similarity = self.compare_cosine_similarity(code)
|
||||
|
||||
return distance < settings.FACE_RECOGNITION_DISTANCE_THRESHOLD \
|
||||
and similarity > settings.FACE_RECOGNITION_COSINE_THRESHOLD
|
||||
|
||||
def compare_euclidean_distance(self, base64_vector: str) -> float:
|
||||
target_vector = self._decode_base64_vector(base64_vector)
|
||||
current_vector = self.get_face_vector()
|
||||
return self._calculate_euclidean_distance(current_vector, target_vector)
|
||||
|
||||
def compare_cosine_similarity(self, base64_vector: str) -> float:
|
||||
target_vector = self._decode_base64_vector(base64_vector)
|
||||
current_vector = self.get_face_vector()
|
||||
return self._calculate_cosine_similarity(current_vector, target_vector)
|
||||
|
||||
@staticmethod
|
||||
def _decode_base64_vector(base64_vector: str) -> list[float]:
|
||||
byte_data = base64.b64decode(base64_vector)
|
||||
return list(struct.unpack('<128d', byte_data))
|
||||
|
||||
@staticmethod
|
||||
def _calculate_euclidean_distance(vec1: list[float], vec2: list[float]) -> float:
|
||||
return sum((x - y) ** 2 for x, y in zip(vec1, vec2)) ** 0.5
|
||||
|
||||
@staticmethod
|
||||
def _calculate_cosine_similarity(vec1: list[float], vec2: list[float]) -> float:
|
||||
dot_product = sum(x * y for x, y in zip(vec1, vec2))
|
||||
magnitude_vec1 = math.sqrt(sum(x ** 2 for x in vec1))
|
||||
magnitude_vec2 = math.sqrt(sum(y ** 2 for y in vec2))
|
||||
if magnitude_vec1 == 0 or magnitude_vec2 == 0:
|
||||
raise ValueError("Vector magnitude cannot be zero.")
|
||||
return dot_product / (magnitude_vec1 * magnitude_vec2)
|
||||
Reference in New Issue
Block a user