Refactor authentication logic to unify user account handling and update database schema for user accounts

This commit is contained in:
zyh
2025-08-24 15:54:21 +08:00
parent be437a360d
commit c65c03b933
22 changed files with 256 additions and 288 deletions

View File

@@ -1,11 +1,9 @@
package com.gameplatform.server.service.auth;
import com.gameplatform.server.mapper.admin.AdminUserMapper;
import com.gameplatform.server.mapper.agent.AgentMapper;
import com.gameplatform.server.mapper.account.UserAccountMapper;
import com.gameplatform.server.model.dto.auth.LoginRequest;
import com.gameplatform.server.model.dto.auth.LoginResponse;
import com.gameplatform.server.model.entity.admin.AdminUser;
import com.gameplatform.server.model.entity.agent.Agent;
import com.gameplatform.server.model.entity.account.UserAccount;
import com.gameplatform.server.security.JwtService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@@ -16,78 +14,62 @@ import java.util.Map;
@Service
public class AuthService {
private final AdminUserMapper adminUserMapper;
private final AgentMapper agentMapper;
private final UserAccountMapper userAccountMapper;
private final PasswordEncoder passwordEncoder;
private final JwtService jwtService;
public AuthService(AdminUserMapper adminUserMapper,
AgentMapper agentMapper,
public AuthService(UserAccountMapper userAccountMapper,
PasswordEncoder passwordEncoder,
JwtService jwtService) {
this.adminUserMapper = adminUserMapper;
this.agentMapper = agentMapper;
this.userAccountMapper = userAccountMapper;
this.passwordEncoder = passwordEncoder;
this.jwtService = jwtService;
}
public Mono<LoginResponse> login(LoginRequest req) {
String userType = req.getUserType().toLowerCase();
if ("admin".equals(userType)) {
return Mono.fromCallable(() -> adminUserMapper.findByUsername(req.getUsername()))
.subscribeOn(Schedulers.boundedElastic())
.flatMap(admin -> validateAdminPassword(admin, req.getPassword()));
} else if ("agent".equals(userType)) {
return Mono.fromCallable(() -> agentMapper.findByLoginAccount(req.getUsername()))
.subscribeOn(Schedulers.boundedElastic())
.flatMap(agent -> validateAgentPassword(agent, req.getPassword()));
String userType = normalizeType(req.getUserType());
return Mono.fromCallable(() -> userAccountMapper.findByUsernameAndType(req.getUsername(), userType))
.subscribeOn(Schedulers.boundedElastic())
.flatMap(acc -> validatePasswordAndBuild(acc, userType, req.getPassword()));
}
private String normalizeType(String t) {
if (t == null) return "";
t = t.trim().toLowerCase();
if ("admin".equals(t)) return "ADMIN";
if ("agent".equals(t)) return "AGENT";
throw new IllegalArgumentException("unsupported userType: " + t);
}
private Mono<LoginResponse> validatePasswordAndBuild(UserAccount acc, String userType, String rawPwd) {
if (acc == null || acc.getPasswordHash() == null) {
return Mono.error(new IllegalArgumentException("用户名或密码错误"));
}
boolean ok;
String hash = acc.getPasswordHash();
if (hash.startsWith("$2a$") || hash.startsWith("$2b$") || hash.startsWith("$2y$")) {
ok = passwordEncoder.matches(rawPwd, hash);
} else if (hash.startsWith("PLAIN:")) {
ok = rawPwd.equals(hash.substring(6));
} else {
return Mono.error(new IllegalArgumentException("unsupported userType: " + userType));
ok = false;
}
}
private Mono<LoginResponse> validateAdminPassword(AdminUser admin, String rawPassword) {
if (admin == null || admin.getPasswordHash() == null) {
return Mono.error(new IllegalArgumentException("用户名或密码错误"));
}
boolean ok = passwordEncoder.matches(rawPassword, admin.getPasswordHash());
if (!ok) return Mono.error(new IllegalArgumentException("用户名或密码错误"));
if (!"ENABLED".equalsIgnoreCase(admin.getStatus())) {
if (!"ENABLED".equalsIgnoreCase(acc.getStatus())) {
return Mono.error(new IllegalStateException("账户已禁用"));
}
String token = jwtService.generateToken(
"admin:" + admin.getId(),
"admin", admin.getId(), admin.getUsername(), Map.of("role", admin.getRole())
userType.toLowerCase() + ":" + acc.getId(),
userType.toLowerCase(), acc.getId(), acc.getUsername(),
userType.equals("ADMIN") ? Map.of("role", acc.getRole()) : Map.of("displayName", acc.getDisplayName())
);
LoginResponse resp = new LoginResponse();
resp.setAccessToken(token);
resp.setUserType("admin");
resp.setUserId(admin.getId());
resp.setUsername(admin.getUsername());
resp.setExpiresIn(60L * 30); // align with default 30min
return Mono.just(resp);
}
private Mono<LoginResponse> validateAgentPassword(Agent agent, String rawPassword) {
if (agent == null || agent.getPasswordHash() == null) {
return Mono.error(new IllegalArgumentException("用户名或密码错误"));
}
boolean ok = passwordEncoder.matches(rawPassword, agent.getPasswordHash());
if (!ok) return Mono.error(new IllegalArgumentException("用户名或密码错误"));
if (!"ENABLED".equalsIgnoreCase(agent.getStatus())) {
return Mono.error(new IllegalStateException("账户已禁用"));
}
String token = jwtService.generateToken(
"agent:" + agent.getId(),
"agent", agent.getId(), agent.getLoginAccount(), Map.of("name", agent.getName())
);
LoginResponse resp = new LoginResponse();
resp.setAccessToken(token);
resp.setUserType("agent");
resp.setUserId(agent.getId());
resp.setUsername(agent.getLoginAccount());
resp.setUserType(userType.toLowerCase());
resp.setUserId(acc.getId());
resp.setUsername(acc.getUsername());
resp.setExpiresIn(60L * 30);
return Mono.just(resp);
}
}