mirror of
https://gitee.com/dromara/MaxKey.git
synced 2025-12-06 08:59:10 +08:00
fix: 修复PasskeyRegistrationEndpoint中@PathVariable注解缺少value属性的问题
This commit is contained in:
parent
33734f1387
commit
0733ce2d17
@ -54,7 +54,6 @@ allprojects {
|
||||
targetCompatibility = 17
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
|
||||
compileJava.options.compilerArgs += ['-parameters']
|
||||
eclipse {
|
||||
/*设置工程字符集*/
|
||||
jdt {
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
package org.dromara.maxkey.persistence.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
@ -70,7 +71,7 @@ public interface PasskeyChallengeMapper extends IJpaMapper<PasskeyChallenge> {
|
||||
@Result(column = "status", property = "status"),
|
||||
@Result(column = "inst_id", property = "instId")
|
||||
})
|
||||
PasskeyChallenge findLatestByUserIdAndType(String userId, String challengeType);
|
||||
PasskeyChallenge findLatestByUserIdAndType(@Param("userId") String userId, @Param("challengeType") String challengeType);
|
||||
|
||||
/**
|
||||
* 删除指定挑战ID的记录
|
||||
@ -106,7 +107,7 @@ public interface PasskeyChallengeMapper extends IJpaMapper<PasskeyChallenge> {
|
||||
* @return 清理的记录数
|
||||
*/
|
||||
@Delete("DELETE FROM mxk_passkey_challenges WHERE user_id = #{userId} AND challenge_type = #{challengeType}")
|
||||
int deleteByUserIdAndType(String userId, String challengeType);
|
||||
int deleteByUserIdAndType(@Param("userId") String userId, @Param("challengeType") String challengeType);
|
||||
|
||||
/**
|
||||
* 统计指定用户的挑战数量
|
||||
|
||||
@ -19,6 +19,7 @@ package org.dromara.maxkey.persistence.mapper;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
@ -102,7 +103,7 @@ public interface UserPasskeyMapper extends IJpaMapper<UserPasskey> {
|
||||
@Result(column = "status", property = "status"),
|
||||
@Result(column = "inst_id", property = "instId")
|
||||
})
|
||||
UserPasskey findByUserIdAndCredentialId(String userId, String credentialId);
|
||||
UserPasskey findByUserIdAndCredentialId(@Param("userId") String userId, @Param("credentialId") String credentialId);
|
||||
|
||||
/**
|
||||
* 更新签名计数器
|
||||
@ -112,7 +113,7 @@ public interface UserPasskeyMapper extends IJpaMapper<UserPasskey> {
|
||||
* @return 更新的记录数
|
||||
*/
|
||||
@Update("UPDATE mxk_user_passkeys SET signature_count = #{signatureCount}, last_used_date = NOW() WHERE credential_id = #{credentialId}")
|
||||
int updateSignatureCount(String credentialId, Long signatureCount);
|
||||
int updateSignatureCount(@Param("credentialId") String credentialId, @Param("signatureCount") Long signatureCount);
|
||||
|
||||
/**
|
||||
* 物理删除Passkey
|
||||
@ -122,7 +123,7 @@ public interface UserPasskeyMapper extends IJpaMapper<UserPasskey> {
|
||||
* @return 删除的记录数
|
||||
*/
|
||||
@Delete("DELETE FROM mxk_user_passkeys WHERE user_id = #{userId} AND credential_id = #{credentialId}")
|
||||
int deleteByUserIdAndCredentialId(String userId, String credentialId);
|
||||
int deleteByUserIdAndCredentialId(@Param("userId") String userId, @Param("credentialId") String credentialId);
|
||||
|
||||
/**
|
||||
* 物理删除过期的Passkey记录
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
# PasskeyServiceImpl 重构总结
|
||||
|
||||
## 重构目标
|
||||
|
||||
本次重构旨在提高 `PasskeyServiceImpl` 类的代码可读性、可维护性和可测试性,通过方法拆分和工具类提取来优化代码结构。
|
||||
|
||||
## 主要改进
|
||||
|
||||
### 1. 方法拆分
|
||||
|
||||
#### 原有的大方法被拆分为更小、职责单一的方法:
|
||||
|
||||
**`generateRegistrationOptions` 方法拆分:**
|
||||
- `generateAndSaveChallenge()` - 生成并保存挑战
|
||||
- `buildRegistrationOptions()` - 构建注册选项
|
||||
- `buildRelyingPartyInfo()` - 构建RP信息
|
||||
- `buildUserInfo()` - 构建用户信息
|
||||
- `buildPublicKeyCredentialParams()` - 构建公钥凭据参数
|
||||
- `buildAuthenticatorSelection()` - 构建认证器选择标准
|
||||
- `buildExcludeCredentials()` - 构建排除凭据列表
|
||||
|
||||
**`verifyRegistrationResponse` 方法拆分:**
|
||||
- `validateChallenge()` - 验证挑战
|
||||
- `parseRegistrationResponse()` - 解析注册响应
|
||||
- `createServerProperty()` - 创建服务器属性
|
||||
- `performRegistrationVerification()` - 执行注册验证
|
||||
- `createUserPasskey()` - 创建UserPasskey对象
|
||||
|
||||
**`verifyAuthenticationResponse` 方法拆分:**
|
||||
- `validateChallenge()` - 验证挑战(复用)
|
||||
- `parseAuthenticationResponse()` - 解析认证响应
|
||||
- `validateChallengeUserMatch()` - 验证挑战与用户匹配
|
||||
- `performAuthenticationVerification()` - 执行认证验证
|
||||
- `buildCredentialRecord()` - 构建凭据记录
|
||||
|
||||
### 2. 工具类提取
|
||||
|
||||
创建了 `PasskeyUtils` 工具类,提取了通用的验证和构建逻辑:
|
||||
|
||||
- `generateChallenge()` - 生成挑战
|
||||
- `buildRelyingPartyInfo()` - 构建RP信息
|
||||
- `buildUserInfo()` - 构建用户信息
|
||||
- `buildPublicKeyCredentialParams()` - 构建公钥凭据参数
|
||||
- `buildAuthenticatorSelection()` - 构建认证器选择
|
||||
- `buildCredentialList()` - 构建凭据列表
|
||||
- `createServerProperty()` - 创建服务器属性
|
||||
- `parseAndValidateOrigin()` - 解析和验证origin
|
||||
- `base64Decode()` / `base64Encode()` - Base64编解码
|
||||
- `validateNotEmpty()` / `validateNotNull()` - 参数验证
|
||||
|
||||
### 3. 常量定义
|
||||
|
||||
添加了常量定义以提高代码可读性:
|
||||
|
||||
```java
|
||||
private static final String CHALLENGE_TYPE_REGISTRATION = "registration";
|
||||
private static final String CHALLENGE_TYPE_AUTHENTICATION = "authentication";
|
||||
private static final String CREDENTIAL_TYPE_PUBLIC_KEY = "public-key";
|
||||
private static final String DEFAULT_INST_ID = "1";
|
||||
private static final String DEFAULT_DEVICE_NAME = "Unknown Device";
|
||||
```
|
||||
|
||||
### 4. 内部类优化
|
||||
|
||||
添加了 `AuthenticationResponseData` 内部类来封装认证响应数据,提高代码的组织性。
|
||||
|
||||
### 5. 日志优化
|
||||
|
||||
- 简化了冗长的调试日志
|
||||
- 将详细的调试信息改为debug级别
|
||||
- 保留了关键的错误和警告日志
|
||||
|
||||
## 重构效果
|
||||
|
||||
### 代码质量提升:
|
||||
1. **可读性**:方法职责更加单一,代码逻辑更清晰
|
||||
2. **可维护性**:功能模块化,便于修改和扩展
|
||||
3. **可测试性**:小方法更容易进行单元测试
|
||||
4. **复用性**:工具类方法可在其他地方复用
|
||||
|
||||
### 代码行数优化:
|
||||
- 原文件:约900行
|
||||
- 重构后主文件:约774行
|
||||
- 新增工具类:约238行
|
||||
- 总体代码更加模块化和组织化
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
passkey/
|
||||
├── service/impl/
|
||||
│ └── PasskeyServiceImpl.java (重构后的主实现类)
|
||||
└── util/
|
||||
└── PasskeyUtils.java (新增的工具类)
|
||||
```
|
||||
|
||||
## 向后兼容性
|
||||
|
||||
本次重构保持了所有公共接口的兼容性,不会影响现有的调用代码。所有的重构都是内部实现的优化,对外部调用者透明。
|
||||
|
||||
## 后续建议
|
||||
|
||||
1. 为新的私有方法添加单元测试
|
||||
2. 考虑将一些配置参数提取到配置文件中
|
||||
3. 可以进一步优化异常处理机制
|
||||
4. 考虑添加更多的参数验证逻辑
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -156,7 +156,7 @@ public class PasskeyRegistrationEndpoint {
|
||||
*/
|
||||
@GetMapping("/list/{userId}")
|
||||
public ResponseEntity<?> getUserPasskeys(
|
||||
@PathVariable String userId,
|
||||
@PathVariable("userId") String userId,
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse) {
|
||||
|
||||
@ -195,8 +195,8 @@ public class PasskeyRegistrationEndpoint {
|
||||
*/
|
||||
@DeleteMapping("/delete/{userId}/{credentialId}")
|
||||
public ResponseEntity<?> deletePasskey(
|
||||
@PathVariable String userId,
|
||||
@PathVariable String credentialId,
|
||||
@PathVariable("userId") String userId,
|
||||
@PathVariable("credentialId") String credentialId,
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse) {
|
||||
|
||||
@ -240,7 +240,7 @@ public class PasskeyRegistrationEndpoint {
|
||||
*/
|
||||
@GetMapping("/stats/{userId}")
|
||||
public ResponseEntity<?> getPasskeyStats(
|
||||
@PathVariable String userId,
|
||||
@PathVariable("userId") String userId,
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse) {
|
||||
|
||||
@ -273,7 +273,7 @@ public class PasskeyRegistrationEndpoint {
|
||||
*/
|
||||
@GetMapping("/support/{userId}")
|
||||
public ResponseEntity<?> checkPasskeySupport(
|
||||
@PathVariable String userId,
|
||||
@PathVariable("userId") String userId,
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse) {
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "maxkey",
|
||||
"version": "4.1.0",
|
||||
"version": "4.1.x",
|
||||
"description": "Leading-Edge IAM Identity and Access Management",
|
||||
"author": "MaxKey <support@maxsso.net>",
|
||||
"repository": {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
|
||||
* Copyright [2025] [MaxKey of copyright http://www.maxkey.top]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@ -32,26 +32,6 @@
|
||||
</div>
|
||||
<div nz-col nzXs="24" nzSm="12" nzMd="6" class="mb-md">
|
||||
<div nz-row nzType="flex" nzAlign="middle" class="bg-success rounded-md">
|
||||
<div nz-col nzSpan="12" class="p-md text-white">
|
||||
<div class="h2 mt0">{{ dayCount }}</div>
|
||||
<p class="text-nowrap mb0">{{ 'mxk.home.dayCount' | i18n }}</p>
|
||||
</div>
|
||||
<div nz-col nzSpan="12">
|
||||
<g2-mini-bar
|
||||
*ngIf="simulateData"
|
||||
height="35"
|
||||
color="#fff"
|
||||
borderWidth="3"
|
||||
[padding]="[5, 30]"
|
||||
[data]="simulateData"
|
||||
tooltipType="mini"
|
||||
(ready)="fixDark($event)"
|
||||
></g2-mini-bar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div nz-col nzXs="24" nzSm="12" nzMd="6" class="mb-md">
|
||||
<div nz-row nzType="flex" nzAlign="middle" class="bg-orange rounded-md">
|
||||
<div nz-col nzSpan="12" class="p-md text-white">
|
||||
<div class="h2 mt0">{{ newUsers }}</div>
|
||||
<p class="text-nowrap mb0">{{ 'mxk.home.newUsers' | i18n }}</p>
|
||||
|
||||
@ -52,7 +52,6 @@ dependencies {
|
||||
implementation project(":maxkey-starter:maxkey-starter-sms")
|
||||
implementation project(":maxkey-starter:maxkey-starter-social")
|
||||
implementation project(":maxkey-starter:maxkey-starter-web")
|
||||
implementation project(":maxkey-starter:maxkey-starter-passkey")
|
||||
|
||||
implementation project(":maxkey-authentications:maxkey-authentication-core")
|
||||
implementation project(":maxkey-authentications:maxkey-authentication-provider")
|
||||
@ -65,11 +64,4 @@ dependencies {
|
||||
implementation project(":maxkey-protocols:maxkey-protocol-oauth-2.0")
|
||||
implementation project(":maxkey-protocols:maxkey-protocol-saml-2.0")
|
||||
implementation project(":maxkey-protocols:maxkey-protocol-jwt")
|
||||
|
||||
// WebAuthn4J 完整依赖
|
||||
implementation "com.webauthn4j:webauthn4j-core:${webauthn4jVersion}"
|
||||
implementation "com.webauthn4j:webauthn4j-util:${webauthn4jVersion}"
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-cbor'
|
||||
implementation 'commons-codec:commons-codec'
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user