Skip to content

Commit

Permalink
实现人脸验证
Browse files Browse the repository at this point in the history
  • Loading branch information
xfqwdsj committed May 3, 2024
1 parent 1ad0cdf commit 75fc033
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 47 deletions.
55 changes: 27 additions & 28 deletions py-common/src/commonMain/kotlin/Message.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,7 @@ sealed class Message {
@Serializable
sealed class Handshake : Message() {
@Serializable
data class Request(val userId: String, val mode: Mode) : Handshake() {
@Serializable
enum class Mode {
Register, Verify;

internal companion object
}

data class Request(val userId: String) : Handshake() {
internal companion object
}

Expand All @@ -51,38 +44,44 @@ sealed class Message {
}

@Serializable
data class Frame(val userId: String, val format: FrameFormat, val width: Int, val content: ByteArray) : Message() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
sealed class Client : Message() {
@Serializable
data class Frame(val userId: String, val format: FrameFormat, val width: Int, val content: ByteArray) :
Client() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false

other as Frame
other as Frame

if (userId != other.userId) return false
if (!content.contentEquals(other.content)) return false
if (userId != other.userId) return false
if (!content.contentEquals(other.content)) return false

return true
}
return true
}

override fun hashCode(): Int {
var result = userId.hashCode()
result = 31 * result + content.contentHashCode()
return result
}
override fun hashCode(): Int {
var result = userId.hashCode()
result = 31 * result + content.contentHashCode()
return result
}

@Serializable
enum class FrameFormat {
Rgb;
@Serializable
enum class FrameFormat {
Rgb;

internal companion object
}

internal companion object
}

@Serializable
data object Cancel : Client()

internal companion object
}

@Serializable
data object Cancel : Message()

@Serializable
sealed class Result : Message() {
/**
Expand Down
68 changes: 50 additions & 18 deletions server/src/main/kotlin/api/Auth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ private fun Route.apiAuthRequest() = rateLimit(rateLimitName) {
Face -> {
select {
application.launch {
if (sendMessageToPy(message = Message.Ping.Request) is Message.Ping.Response) {
if (sendMessageToPy(Message.Ping.Request) is Message.Ping.Response) {
logger.debug("Responding face request with success.")
call.respondRequestResult(Api.Auth.Type.Request.ResponseBody.Success(token))
} else {
Expand Down Expand Up @@ -232,43 +232,82 @@ private fun Route.apiAuthVerify() = post<Api.Auth.Type.Verify> { req ->

when (token.verificationType) {
FhraiseToken, QrCode, SmsCode, EmailCode -> call.respondCodeVerificationResult(token, req, body)
Face -> call.respondFaceVerificationResult(token, req, body)
Face -> call.respondVerificationResult(Api.Auth.Type.Verify.ResponseBody.Failure) // 人脸验证使用 WebSocket
Password -> call.respondPasswordVerificationResult(token, req, body)
}
}

@OptIn(ExperimentalCoroutinesApi::class)
private fun Route.apiAuthFace() = webSocket(Api.Auth.Face.PATH) {
suspend fun close(message: String, reason: CloseReason.Codes = CloseReason.Codes.VIOLATED_POLICY) =
close(CloseReason(reason, message))

val handshakeRequest = select {
async {
runCatching { receiveDeserialized<Api.Auth.Face.Handshake.Request>() }.getOrElse {
sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Failure)
close(CloseReason(CloseReason.Codes.VIOLATED_POLICY, "Invalid handshake request."))
close("Invalid handshake request.")
logger.error("Client sent invalid handshake request.", it)
error("Client sent invalid handshake request.")
}
}.onAwait {
it.also { sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Success) }
}
}.onAwait { it }
onTimeout(5.seconds) {
sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Failure)
close(CloseReason(CloseReason.Codes.VIOLATED_POLICY, "Handshake timed out."))
close("Handshake timed out.")
error("Client did not send handshake request.")
}
}

val token = verifiedJwtOrNull(handshakeRequest.token)?.decodedPayloadOrNull<AuthProcessToken>() ?: run {
close(CloseReason(CloseReason.Codes.VIOLATED_POLICY, "Invalid token."))
return@webSocket
sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Failure)
return@webSocket close("Invalid token.")
}

if (token.verificationType != Face) {
close(CloseReason(CloseReason.Codes.VIOLATED_POLICY, "Invalid token type."))
return@webSocket
sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Failure)
return@webSocket close("Invalid token type.")
}

val pyHandshakeResult = sendMessageToPy(Message.Handshake.Request(token.userId))

if (pyHandshakeResult !is Message.Handshake.Response.Success) {
sendSerialized<Api.Auth.Face.Handshake.Response>(Api.Auth.Face.Handshake.Response.Failure)
return@webSocket close("Handshake failed.")
}

while (true) {
val clientMessage = runCatching { receiveDeserialized<Message.Client>() }.getOrElse {
logger.error("Client sent invalid message.", it)
return@webSocket close("Invalid message.")
}

if (clientMessage is Message.Client.Cancel) {
close("Client cancelled.", CloseReason.Codes.NORMAL)
sendMessageToPy(clientMessage)
return@webSocket
}

val pyResult = sendMessageToPy(clientMessage)

if (pyResult !is Message.Result) {
close("Internal error.", CloseReason.Codes.INTERNAL_ERROR)
sendMessageToPy(Message.Client.Cancel)
return@webSocket
}

sendSerialized<Message.Result>(pyResult)

when (pyResult) {
is Message.Result.InternalError, is Message.Result.Cancelled -> {
return@webSocket close("Internal error.", CloseReason.Codes.INTERNAL_ERROR)
}

is Message.Result.Success -> {
return@webSocket close("Success.", CloseReason.Codes.NORMAL)
}

else -> {}
}
}
}

Expand Down Expand Up @@ -305,13 +344,6 @@ private suspend fun RoutingCall.respondCodeVerificationResult(
}
}

private suspend fun RoutingCall.respondFaceVerificationResult(
token: AuthProcessToken, request: Api.Auth.Type.Verify, body: Api.Auth.Type.Verify.RequestBody
) {
// TODO
respondVerificationResult(Api.Auth.Type.Verify.ResponseBody.Failure)
}

private suspend fun RoutingCall.respondPasswordVerificationResult(
token: AuthProcessToken, request: Api.Auth.Type.Verify, body: Api.Auth.Type.Verify.RequestBody
) {
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/kotlin/py/Py.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun Route.py() {
}

suspend fun sendMessageToPy(
id: String = UUID.randomUUID().toString(), message: Message
message: Message, id: String = UUID.randomUUID().toString()
): Message {
messageToPyFlow.emit(id to message)
return messageFromPyFlow.take(id)
Expand Down

0 comments on commit 75fc033

Please sign in to comment.