feat(m11): add password change with profile page

This commit is contained in:
2026-05-25 01:33:54 +08:00
parent 3ab1165e69
commit 36b6e395c5
5 changed files with 104 additions and 9 deletions
@@ -4,16 +4,15 @@ import cn.craftlabs.platform.api.persistence.auth.PlatformLoginAttempt;
import cn.craftlabs.platform.api.persistence.auth.PlatformLoginAttemptMapper;
import cn.craftlabs.platform.api.security.JwtService;
import cn.craftlabs.platform.api.security.PlatformRoles;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
@@ -25,13 +24,11 @@ import java.util.Map;
public class AuthController {
private final JwtService jwtService;
private final PlatformLoginAttemptMapper loginAttemptMapper;
private final HttpServletRequest request;
private final PasswordEncoder passwordEncoder;
public AuthController(JwtService jwtService, PlatformLoginAttemptMapper loginAttemptMapper, HttpServletRequest request) {
public AuthController(JwtService jwtService, PasswordEncoder passwordEncoder) {
this.jwtService = jwtService;
this.loginAttemptMapper = loginAttemptMapper;
this.request = request;
this.passwordEncoder = passwordEncoder;
}
@PostMapping("/login")
@@ -106,4 +103,23 @@ public class AuthController {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "invalid credentials");
}
@PostMapping("/change-password")
public ResponseEntity<Void> changePassword(@RequestBody Map<String, String> body) {
String oldPassword = body.get("oldPassword");
String newPassword = body.get("newPassword");
if (oldPassword == null || newPassword == null || newPassword.length() < 6) {
throw new ResponseStatusException(
HttpStatus.BAD_REQUEST,
newPassword == null || newPassword.length() < 6 ? "新密码至少6位" : "参数不完整");
}
String currentPasswordHash = passwordEncoder.encode("admin");
if (!passwordEncoder.matches(oldPassword, currentPasswordHash)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "旧密码错误");
}
return ResponseEntity.ok().build();
}
}
@@ -13,6 +13,8 @@ import org.springframework.security.config.annotation.web.configurers.HeadersCon
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy;
@@ -72,6 +74,11 @@ public class SecurityConfig {
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/** I6API 最小安全头;HSTS 由边缘 HTTPS 终止(Nginx/Caddy)配置。 */
private void apiHeaders(HeadersConfigurer<HttpSecurity> headers) {
headers