|
@@ -16,13 +16,16 @@ import com.haha.service.DataPermissionService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
+import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.UUID;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -40,6 +43,13 @@ public class AdminLoginServiceImpl implements AdminLoginService {
|
|
|
|
|
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private DataPermissionService dataPermissionService;
|
|
private DataPermissionService dataPermissionService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private StringRedisTemplate stringRedisTemplate;
|
|
|
|
|
+
|
|
|
|
|
+ private static final String REFRESH_TOKEN_PREFIX = "refreshToken:admin:";
|
|
|
|
|
+ private static final Duration REFRESH_TOKEN_TTL = Duration.ofDays(7);
|
|
|
|
|
+ private static final int TOKEN_TIMEOUT_SECONDS = 28800;
|
|
|
|
|
|
|
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
|
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
|
|
|
|
|
|
@@ -74,35 +84,19 @@ public class AdminLoginServiceImpl implements AdminLoginService {
|
|
|
|
|
|
|
|
// 使用Sa-Token进行登录,生成token
|
|
// 使用Sa-Token进行登录,生成token
|
|
|
StpUtil.login(admin.getId());
|
|
StpUtil.login(admin.getId());
|
|
|
- String token = StpUtil.getTokenValue();
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 在Session中存储用户信息
|
|
// 在Session中存储用户信息
|
|
|
StpUtil.getSession().set("username", admin.getUsername());
|
|
StpUtil.getSession().set("username", admin.getUsername());
|
|
|
StpUtil.getSession().set("realName", admin.getRealName());
|
|
StpUtil.getSession().set("realName", admin.getRealName());
|
|
|
StpUtil.getSession().set("roleIds", admin.getRoleIds());
|
|
StpUtil.getSession().set("roleIds", admin.getRoleIds());
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 获取并存储用户权限列表
|
|
// 获取并存储用户权限列表
|
|
|
List<String> permissions = getUserPermissions("1");
|
|
List<String> permissions = getUserPermissions("1");
|
|
|
StpUtil.getSession().set("permissions", permissions);
|
|
StpUtil.getSession().set("permissions", permissions);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
log.info("【临时测试账号】登录成功: username={}, userId={}", username, admin.getId());
|
|
log.info("【临时测试账号】登录成功: username={}, userId={}", username, admin.getId());
|
|
|
-
|
|
|
|
|
- // 构建返回数据
|
|
|
|
|
- UserVO userVO = UserVO.builder()
|
|
|
|
|
- .id(admin.getId())
|
|
|
|
|
- .nickname(admin.getRealName())
|
|
|
|
|
- .avatar(admin.getAvatar())
|
|
|
|
|
- .phone(admin.getPhone())
|
|
|
|
|
- .roles(List.of("admin"))
|
|
|
|
|
- .permissions(permissions)
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- LoginVO loginVO = LoginVO.builder()
|
|
|
|
|
- .token(token)
|
|
|
|
|
- .userInfo(userVO)
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- return Result.success("登录成功", loginVO);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success("登录成功", buildLoginResult(admin, permissions, List.of("admin")));
|
|
|
}
|
|
}
|
|
|
// ====== 以上为临时测试逻辑,生产环境必须移除 ======
|
|
// ====== 以上为临时测试逻辑,生产环境必须移除 ======
|
|
|
|
|
|
|
@@ -135,8 +129,7 @@ public class AdminLoginServiceImpl implements AdminLoginService {
|
|
|
|
|
|
|
|
// 使用Sa-Token进行登录,生成token
|
|
// 使用Sa-Token进行登录,生成token
|
|
|
StpUtil.login(admin.getId());
|
|
StpUtil.login(admin.getId());
|
|
|
- String token = StpUtil.getTokenValue();
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 在Session中存储用户信息
|
|
// 在Session中存储用户信息
|
|
|
StpUtil.getSession().set("username", admin.getUsername());
|
|
StpUtil.getSession().set("username", admin.getUsername());
|
|
|
StpUtil.getSession().set("realName", admin.getRealName());
|
|
StpUtil.getSession().set("realName", admin.getRealName());
|
|
@@ -150,23 +143,8 @@ public class AdminLoginServiceImpl implements AdminLoginService {
|
|
|
List<String> roleCodes = getRoleCodes(admin.getRoleIds());
|
|
List<String> roleCodes = getRoleCodes(admin.getRoleIds());
|
|
|
|
|
|
|
|
log.info("管理员登录成功: username={}, userId={}", username, admin.getId());
|
|
log.info("管理员登录成功: username={}, userId={}", username, admin.getId());
|
|
|
-
|
|
|
|
|
- // 构建返回数据
|
|
|
|
|
- UserVO userVO = UserVO.builder()
|
|
|
|
|
- .id(admin.getId())
|
|
|
|
|
- .nickname(admin.getRealName() != null ? admin.getRealName() : admin.getUsername())
|
|
|
|
|
- .avatar(admin.getAvatar())
|
|
|
|
|
- .phone(admin.getPhone())
|
|
|
|
|
- .roles(roleCodes)
|
|
|
|
|
- .permissions(permissions)
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- LoginVO loginVO = LoginVO.builder()
|
|
|
|
|
- .token(token)
|
|
|
|
|
- .userInfo(userVO)
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- return Result.success("登录成功", loginVO);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success("登录成功", buildLoginResult(admin, permissions, roleCodes));
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("登录异常: username={}, error={}", username, e.getMessage(), e);
|
|
log.error("登录异常: username={}, error={}", username, e.getMessage(), e);
|
|
@@ -261,4 +239,78 @@ public class AdminLoginServiceImpl implements AdminLoginService {
|
|
|
return List.of();
|
|
return List.of();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 构建登录返回结果(含 refreshToken)
|
|
|
|
|
+ */
|
|
|
|
|
+ private LoginVO buildLoginResult(Admin admin, List<String> permissions, List<String> roles) {
|
|
|
|
|
+ String token = StpUtil.getTokenValue();
|
|
|
|
|
+ String refreshToken = UUID.randomUUID().toString();
|
|
|
|
|
+
|
|
|
|
|
+ // 将 refreshToken 存入 Redis,关联 userId
|
|
|
|
|
+ stringRedisTemplate.opsForValue().set(
|
|
|
|
|
+ REFRESH_TOKEN_PREFIX + refreshToken,
|
|
|
|
|
+ admin.getId().toString(),
|
|
|
|
|
+ REFRESH_TOKEN_TTL
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ UserVO userVO = UserVO.builder()
|
|
|
|
|
+ .id(admin.getId())
|
|
|
|
|
+ .nickname(admin.getRealName() != null ? admin.getRealName() : admin.getUsername())
|
|
|
|
|
+ .avatar(admin.getAvatar())
|
|
|
|
|
+ .phone(admin.getPhone())
|
|
|
|
|
+ .roles(roles)
|
|
|
|
|
+ .permissions(permissions)
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ return LoginVO.builder()
|
|
|
|
|
+ .token(token)
|
|
|
|
|
+ .refreshToken(refreshToken)
|
|
|
|
|
+ .tokenTimeout(TOKEN_TIMEOUT_SECONDS)
|
|
|
|
|
+ .userInfo(userVO)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Result<LoginVO> refreshToken(String refreshToken) {
|
|
|
|
|
+ if (refreshToken == null || refreshToken.isBlank()) {
|
|
|
|
|
+ return Result.error(400, "refreshToken 不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String key = REFRESH_TOKEN_PREFIX + refreshToken;
|
|
|
|
|
+ String userId = stringRedisTemplate.opsForValue().get(key);
|
|
|
|
|
+
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(401, "refreshToken 无效或已过期");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 删除旧的 refreshToken
|
|
|
|
|
+ stringRedisTemplate.delete(key);
|
|
|
|
|
+
|
|
|
|
|
+ // 注销旧的 Sa-Token 会话(如果存在)
|
|
|
|
|
+ try {
|
|
|
|
|
+ StpUtil.logout(Long.parseLong(userId));
|
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 重新登录
|
|
|
|
|
+ StpUtil.login(Long.parseLong(userId));
|
|
|
|
|
+
|
|
|
|
|
+ // 从旧 Session 恢复用户信息
|
|
|
|
|
+ // 旧 session 已被注销,需要重新查询
|
|
|
|
|
+ Admin admin = adminMapper.selectById(userId);
|
|
|
|
|
+ if (admin == null) {
|
|
|
|
|
+ return Result.error(404, "管理员不存在或已被删除");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<String> permissions = getUserPermissions(admin.getRoleIds());
|
|
|
|
|
+ List<String> roles = getRoleCodes(admin.getRoleIds());
|
|
|
|
|
+
|
|
|
|
|
+ StpUtil.getSession().set("username", admin.getUsername());
|
|
|
|
|
+ StpUtil.getSession().set("realName", admin.getRealName());
|
|
|
|
|
+ StpUtil.getSession().set("roleIds", admin.getRoleIds());
|
|
|
|
|
+ StpUtil.getSession().set("permissions", permissions);
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success("token 刷新成功", buildLoginResult(admin, permissions, roles));
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|