feat: 个人信息页面.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
### 登陆 - admin 用户
|
||||
### 登录 - admin 用户
|
||||
POST {{baseUrl}}/infra/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
@@ -8,7 +8,7 @@ Content-Type: application/json
|
||||
}
|
||||
|
||||
|
||||
### 登陆
|
||||
### 登录
|
||||
POST {{baseUrl}}/infra/auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.orion.ops.module.infra.entity.request.user.UserLoginRequest;
|
||||
import com.orion.ops.module.infra.entity.request.user.UserUpdatePasswordRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.UserLoginVO;
|
||||
import com.orion.ops.module.infra.service.AuthenticationService;
|
||||
import com.orion.ops.module.infra.service.SystemUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -40,12 +39,9 @@ public class AuthenticationController {
|
||||
@Resource
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
@Resource
|
||||
private SystemUserService systemUserService;
|
||||
|
||||
@OperatorLog(AuthenticationOperatorType.LOGIN)
|
||||
@PermitAll
|
||||
@Operation(summary = "登陆")
|
||||
@Operation(summary = "登录")
|
||||
@PostMapping("/login")
|
||||
public UserLoginVO login(@Validated @RequestBody UserLoginRequest request,
|
||||
HttpServletRequest servletRequest) {
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.ops.framework.common.validator.group.Page;
|
||||
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.infra.entity.request.operator.OperatorLogQueryRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.LoginHistoryVO;
|
||||
import com.orion.ops.module.infra.entity.vo.OperatorLogVO;
|
||||
import com.orion.ops.module.infra.service.OperatorLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -13,12 +15,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志 api
|
||||
@@ -47,5 +47,22 @@ public class OperatorLogController {
|
||||
return operatorLogService.getOperatorLogPage(request);
|
||||
}
|
||||
|
||||
// fixme 权限配置
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/login-history")
|
||||
@Operation(summary = "查询用户登录日志")
|
||||
public List<LoginHistoryVO> getLoginHistory(@RequestParam("username") String username) {
|
||||
return operatorLogService.getLoginHistory(username);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/current-login-history")
|
||||
@Operation(summary = "查询当前用户登录日志")
|
||||
public List<LoginHistoryVO> getCurrentLoginHistory() {
|
||||
String username = SecurityUtils.getLoginUsername();
|
||||
return operatorLogService.getLoginHistory(username);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.orion.ops.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.ops.framework.common.validator.group.Page;
|
||||
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.infra.define.operator.SystemUserOperatorType;
|
||||
import com.orion.ops.module.infra.entity.request.user.*;
|
||||
@@ -95,6 +96,20 @@ public class SystemUserController {
|
||||
return HttpWrapper.ok();
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/get-current")
|
||||
@Operation(summary = "查询当前用户信息")
|
||||
public SystemUserVO getCurrentUserInfo() {
|
||||
return systemUserService.getSystemUserById(SecurityUtils.getLoginUserId());
|
||||
}
|
||||
|
||||
@PutMapping("/update-current")
|
||||
@Operation(summary = "更新当前用户信息")
|
||||
public Integer updateCurrentUser(@Validated @RequestBody SystemUserUpdateRequest request) {
|
||||
request.setId(SecurityUtils.getLoginUserId());
|
||||
return systemUserService.updateSystemUserById(request);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "通过 id 查询用户")
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.orion.ops.module.infra.convert;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
|
||||
import com.orion.ops.module.infra.entity.domain.OperatorLogDO;
|
||||
import com.orion.ops.module.infra.entity.request.operator.OperatorLogQueryRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.LoginHistoryVO;
|
||||
import com.orion.ops.module.infra.entity.vo.OperatorLogVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@@ -25,4 +26,6 @@ public interface OperatorLogConvert {
|
||||
|
||||
OperatorLogVO to(OperatorLogDO domain);
|
||||
|
||||
LoginHistoryVO toLoginHistory(OperatorLogDO domain);
|
||||
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@ public interface UserCacheKeyDefine {
|
||||
|
||||
CacheKeyDefine LOGIN_FAILED_COUNT = new CacheKeyBuilder()
|
||||
.key("user:failed:{}")
|
||||
.desc("用户登陆失败次数 ${username}")
|
||||
.desc("用户登录失败次数 ${username}")
|
||||
.timeout(3, TimeUnit.DAYS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine LOGIN_TOKEN = new CacheKeyBuilder()
|
||||
.key("user:token:{}:{}")
|
||||
.desc("用户登陆 token ${id} ${time}")
|
||||
.desc("用户登录 token ${id} ${time}")
|
||||
.type(LoginTokenDTO.class)
|
||||
.timeout(24, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
@@ -25,7 +25,7 @@ public class AuthenticationOperatorType extends InitializingOperatorTypes {
|
||||
@Override
|
||||
public OperatorType[] types() {
|
||||
return new OperatorType[]{
|
||||
new OperatorType(L, LOGIN, "登陆系统"),
|
||||
new OperatorType(L, LOGIN, "登录系统"),
|
||||
new OperatorType(L, LOGOUT, "登出系统"),
|
||||
new OperatorType(L, UPDATE_PASSWORD, "修改密码"),
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 登陆 token 缓存
|
||||
* 登录 token 缓存
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -28,7 +28,7 @@ public class LoginTokenDTO {
|
||||
*
|
||||
* @see com.orion.ops.module.infra.enums.LoginTokenStatusEnum
|
||||
*/
|
||||
private Integer tokenStatus;
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 已续签次数
|
||||
@@ -36,18 +36,43 @@ public class LoginTokenDTO {
|
||||
private Integer refreshCount;
|
||||
|
||||
/**
|
||||
* 登陆时间/其他设备登陆时间
|
||||
* 原始登录身份
|
||||
*/
|
||||
private Long loginTime;
|
||||
private Identity origin;
|
||||
|
||||
/**
|
||||
* 登陆 ip/其他设备登陆 ip
|
||||
* 覆盖登录身份
|
||||
*/
|
||||
private String ip;
|
||||
private Identity override;
|
||||
|
||||
/**
|
||||
* 登陆地址/其他设备登陆地址
|
||||
* 身份信息
|
||||
*/
|
||||
private String location;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Identity {
|
||||
|
||||
/**
|
||||
* 原始登录时间
|
||||
*/
|
||||
private Long loginTime;
|
||||
|
||||
/**
|
||||
* 当前设备登录地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 当前设备登录地址
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 当前设备 userAgent
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ public class OperatorLogQueryRequest extends PageRequest {
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Size(max = 32)
|
||||
@Schema(description = "模块")
|
||||
private String module;
|
||||
|
||||
@@ -6,14 +6,14 @@ import lombok.Data;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* 登陆请求
|
||||
* 登录请求
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023/7/13 22:16
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "UserLoginRequest", description = "登陆请求")
|
||||
@Schema(name = "UserLoginRequest", description = "登录请求")
|
||||
public class UserLoginRequest {
|
||||
|
||||
@NotEmpty
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.orion.ops.module.infra.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 登录日志 视图响应对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-10-10 17:08
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "LoginHistoryVO", description = "登录日志 视图响应对象")
|
||||
public class LoginHistoryVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "请求ip")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "请求地址")
|
||||
private String location;
|
||||
|
||||
@Schema(description = "userAgent")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(description = "操作结果 0失败 1成功")
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMessage;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 用户登陆响应
|
||||
* 用户登录响应
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -20,7 +20,7 @@ import lombok.NoArgsConstructor;
|
||||
@Schema(name = "SystemUserVO", description = "用户 视图响应对象")
|
||||
public class UserLoginVO {
|
||||
|
||||
@Schema(description = "登陆 token")
|
||||
@Schema(description = "登录 token")
|
||||
private String token;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.orion.ops.module.infra.enums;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 登陆 token 状态
|
||||
* 登录 token 状态
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -18,9 +18,9 @@ public enum LoginTokenStatusEnum {
|
||||
OK(0),
|
||||
|
||||
/**
|
||||
* 已在其他设备登陆
|
||||
* 已在其他设备登录
|
||||
*/
|
||||
OTHER_DEVICE(1, "已在其他设备登陆"),
|
||||
OTHER_DEVICE(1, "已在其他设备登录"),
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
|
||||
}
|
||||
// 检查 token 状态
|
||||
this.checkTokenStatus(tokenInfo);
|
||||
// 获取登陆信息
|
||||
// 获取登录信息
|
||||
LoginUser user = authenticationService.getLoginUser(tokenInfo.getId());
|
||||
// 检查用户状态
|
||||
UserStatusEnum.checkUserStatus(user.getStatus());
|
||||
@@ -70,17 +70,18 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
|
||||
* @param loginToken loginToken
|
||||
*/
|
||||
private void checkTokenStatus(LoginTokenDTO loginToken) {
|
||||
Integer tokenStatus = loginToken.getTokenStatus();
|
||||
Integer tokenStatus = loginToken.getStatus();
|
||||
// 正常状态
|
||||
if (LoginTokenStatusEnum.OK.getStatus().equals(tokenStatus)) {
|
||||
return;
|
||||
}
|
||||
// 其他设备登陆
|
||||
// 其他设备登录
|
||||
if (LoginTokenStatusEnum.OTHER_DEVICE.getStatus().equals(tokenStatus)) {
|
||||
LoginTokenDTO.Identity override = loginToken.getOverride();
|
||||
throw ErrorCode.OTHER_DEVICE_LOGIN.exception(
|
||||
Dates.format(new Date(loginToken.getLoginTime()), Dates.MD_HM),
|
||||
loginToken.getIp(),
|
||||
loginToken.getLocation());
|
||||
Dates.format(new Date(override.getLoginTime()), Dates.MD_HM),
|
||||
override.getAddress(),
|
||||
override.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
public interface AuthenticationService {
|
||||
|
||||
// TODO 配置化
|
||||
// 允许多端登陆
|
||||
// 允许多端登录
|
||||
boolean allowMultiDevice = true;
|
||||
// 允许凭证续签
|
||||
boolean allowRefresh = true;
|
||||
@@ -28,7 +28,7 @@ public interface AuthenticationService {
|
||||
int maxFailedLoginCount = 5;
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
* 登录
|
||||
*
|
||||
* @param request request
|
||||
* @param servletRequest servletRequest
|
||||
@@ -51,7 +51,7 @@ public interface AuthenticationService {
|
||||
void updatePassword(UserUpdatePasswordRequest request);
|
||||
|
||||
/**
|
||||
* 获取登陆用户信息
|
||||
* 获取登录用户信息
|
||||
*
|
||||
* @param userId userId
|
||||
* @return loginUser
|
||||
|
||||
@@ -3,8 +3,11 @@ package com.orion.ops.module.infra.service;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
|
||||
import com.orion.ops.module.infra.entity.request.operator.OperatorLogQueryRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.LoginHistoryVO;
|
||||
import com.orion.ops.module.infra.entity.vo.OperatorLogVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志 服务类
|
||||
*
|
||||
@@ -29,4 +32,12 @@ public interface OperatorLogService {
|
||||
*/
|
||||
DataGrid<OperatorLogVO> getOperatorLogPage(OperatorLogQueryRequest request);
|
||||
|
||||
/**
|
||||
* 查询用户登录日志
|
||||
*
|
||||
* @param username username
|
||||
* @return rows
|
||||
*/
|
||||
List<LoginHistoryVO> getLoginHistory(String username);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,9 +71,9 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
|
||||
@Override
|
||||
public UserLoginVO login(UserLoginRequest request, HttpServletRequest servletRequest) {
|
||||
// 登陆前检查
|
||||
// 登录前检查
|
||||
this.preCheckLogin(request);
|
||||
// 获取登陆用户
|
||||
// 获取登录用户
|
||||
LambdaQueryWrapper<SystemUserDO> wrapper = systemUserDAO.wrapper()
|
||||
.eq(SystemUserDO::getUsername, request.getUsername());
|
||||
SystemUserDO user = systemUserDAO.of(wrapper).getOne();
|
||||
@@ -90,17 +90,18 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
this.deleteUserCache(user);
|
||||
// 重设用户缓存
|
||||
this.setUserCache(user);
|
||||
// 获取登陆 ip
|
||||
// 获取登录信息
|
||||
String remoteAddr = Servlets.getRemoteAddr(servletRequest);
|
||||
String location = IpUtils.getLocation(remoteAddr);
|
||||
String userAgent = Servlets.getUserAgent(servletRequest);
|
||||
long current = System.currentTimeMillis();
|
||||
// 不允许多端登陆
|
||||
// 不允许多端登录
|
||||
if (!allowMultiDevice) {
|
||||
// 无效化其他缓存
|
||||
this.invalidOtherDeviceToken(user.getId(), current, remoteAddr, location);
|
||||
this.invalidOtherDeviceToken(user.getId(), current, remoteAddr, location, userAgent);
|
||||
}
|
||||
// 生成 loginToken
|
||||
String token = this.generatorLoginToken(user, current, remoteAddr, location);
|
||||
String token = this.generatorLoginToken(user, current, remoteAddr, location, userAgent);
|
||||
return UserLoginVO.builder()
|
||||
.token(token)
|
||||
.build();
|
||||
@@ -108,7 +109,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
|
||||
@Override
|
||||
public void logout(HttpServletRequest request) {
|
||||
// 获取登陆 token
|
||||
// 获取登录 token
|
||||
String loginToken = SecurityUtils.obtainAuthorization(request);
|
||||
if (loginToken == null) {
|
||||
return;
|
||||
@@ -156,12 +157,12 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
|
||||
@Override
|
||||
public LoginTokenDTO getLoginTokenInfo(String loginToken, boolean checkRefresh) {
|
||||
// 获取登陆 key pair
|
||||
// 获取登录 key pair
|
||||
Pair<Long, Long> pair = this.getLoginTokenPair(loginToken);
|
||||
if (pair == null) {
|
||||
return null;
|
||||
}
|
||||
// 获取登陆 key value
|
||||
// 获取登录 key value
|
||||
String loginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(pair.getKey(), pair.getValue());
|
||||
String loginCache = redisTemplate.opsForValue().get(loginKey);
|
||||
if (loginCache != null) {
|
||||
@@ -181,7 +182,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
LoginTokenDTO refresh = JSON.parseObject(refreshCache, LoginTokenDTO.class);
|
||||
int refreshCount = refresh.getRefreshCount() + 1;
|
||||
refresh.setRefreshCount(refreshCount);
|
||||
// 设置登陆缓存
|
||||
// 设置登录缓存
|
||||
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, refresh);
|
||||
if (refreshCount < maxRefreshCount) {
|
||||
// 小于续签最大次数 则再次设置 refreshToken
|
||||
@@ -213,7 +214,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆预检查
|
||||
* 登录预检查
|
||||
*
|
||||
* @param request request
|
||||
*/
|
||||
@@ -222,7 +223,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
if (request.getPassword().length() != Const.MD5_LEN) {
|
||||
throw Exceptions.argument(ErrorMessage.USERNAME_PASSWORD_ERROR);
|
||||
}
|
||||
// 检查登陆失败次数
|
||||
// 检查登录失败次数
|
||||
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername());
|
||||
String failedCount = redisTemplate.opsForValue().get(failedCountKey);
|
||||
if (failedCount != null && Integer.parseInt(failedCount) >= maxFailedLoginCount) {
|
||||
@@ -243,7 +244,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
if (user != null && user.getPassword().equals(Signatures.md5(request.getPassword()))) {
|
||||
return true;
|
||||
}
|
||||
// 刷新登陆失败缓存
|
||||
// 刷新登录失败缓存
|
||||
String failedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(request.getUsername());
|
||||
Long failedLoginCount = redisTemplate.opsForValue().increment(failedCountKey);
|
||||
RedisUtils.setExpire(failedCountKey, UserCacheKeyDefine.LOGIN_FAILED_COUNT);
|
||||
@@ -293,7 +294,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
private void deleteUserCache(SystemUserDO user) {
|
||||
// 用户信息缓存
|
||||
String userInfoKey = UserCacheKeyDefine.USER_INFO.format(user.getId());
|
||||
// 登陆失败次数缓存
|
||||
// 登录失败次数缓存
|
||||
String loginFailedCountKey = UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(user.getUsername());
|
||||
// 删除缓存
|
||||
redisTemplate.delete(Lists.of(userInfoKey, loginFailedCountKey));
|
||||
@@ -324,34 +325,34 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 无效化其他登陆信息
|
||||
* 无效化其他登录信息
|
||||
*
|
||||
* @param id id
|
||||
* @param loginTime loginTime
|
||||
* @param remoteAddr remoteAddr
|
||||
* @param location location
|
||||
* @param userAgent userAgent
|
||||
*/
|
||||
@SuppressWarnings("ALL")
|
||||
private void invalidOtherDeviceToken(Long id, long loginTime, String remoteAddr, String location) {
|
||||
private void invalidOtherDeviceToken(Long id, long loginTime,
|
||||
String remoteAddr, String location, String userAgent) {
|
||||
String loginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(id, "*");
|
||||
// 获取登陆信息
|
||||
// 获取登录信息
|
||||
Set<String> loginKeyList = RedisUtils.scanKeys(loginKey);
|
||||
if (!loginKeyList.isEmpty()) {
|
||||
// 获取有效登陆信息
|
||||
// 获取有效登录信息
|
||||
List<LoginTokenDTO> loginTokenInfoList = redisTemplate.opsForValue()
|
||||
.multiGet(loginKeyList)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(s -> JSON.parseObject(s, LoginTokenDTO.class))
|
||||
.filter(s -> LoginTokenStatusEnum.OK.getStatus().equals(s.getTokenStatus()))
|
||||
.filter(s -> LoginTokenStatusEnum.OK.getStatus().equals(s.getStatus()))
|
||||
.collect(Collectors.toList());
|
||||
// 修改登陆信息
|
||||
// 修改登录信息
|
||||
for (LoginTokenDTO loginTokenInfo : loginTokenInfoList) {
|
||||
String deviceLoginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(id, loginTokenInfo.getLoginTime());
|
||||
loginTokenInfo.setTokenStatus(LoginTokenStatusEnum.OTHER_DEVICE.getStatus());
|
||||
loginTokenInfo.setLoginTime(loginTime);
|
||||
loginTokenInfo.setIp(remoteAddr);
|
||||
loginTokenInfo.setLocation(location);
|
||||
String deviceLoginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(id, loginTokenInfo.getOrigin().getLoginTime());
|
||||
loginTokenInfo.setStatus(LoginTokenStatusEnum.OTHER_DEVICE.getStatus());
|
||||
loginTokenInfo.setOverride(new LoginTokenDTO.Identity(loginTime, remoteAddr, location, userAgent));
|
||||
RedisStrings.setJson(deviceLoginKey, UserCacheKeyDefine.LOGIN_TOKEN, loginTokenInfo);
|
||||
}
|
||||
}
|
||||
@@ -372,20 +373,19 @@ public class AuthenticationServiceImpl implements AuthenticationService {
|
||||
* @param loginTime loginTime
|
||||
* @param remoteAddr remoteAddr
|
||||
* @param location location
|
||||
* @param userAgent userAgent
|
||||
* @return loginToken
|
||||
*/
|
||||
private String generatorLoginToken(SystemUserDO user, long loginTime,
|
||||
String remoteAddr, String location) {
|
||||
String remoteAddr, String location, String userAgent) {
|
||||
Long id = user.getId();
|
||||
// 生成 loginToken
|
||||
String loginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(id, loginTime);
|
||||
LoginTokenDTO loginValue = LoginTokenDTO.builder()
|
||||
.id(id)
|
||||
.tokenStatus(LoginTokenStatusEnum.OK.getStatus())
|
||||
.status(LoginTokenStatusEnum.OK.getStatus())
|
||||
.refreshCount(0)
|
||||
.ip(remoteAddr)
|
||||
.loginTime(loginTime)
|
||||
.location(location)
|
||||
.origin(new LoginTokenDTO.Identity(loginTime, remoteAddr, location, userAgent))
|
||||
.build();
|
||||
RedisStrings.setJson(loginKey, UserCacheKeyDefine.LOGIN_TOKEN, loginValue);
|
||||
// 生成 refreshToken
|
||||
|
||||
@@ -3,16 +3,20 @@ package com.orion.ops.module.infra.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.ops.framework.biz.operator.log.core.model.OperatorLogModel;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.module.infra.convert.OperatorLogConvert;
|
||||
import com.orion.ops.module.infra.dao.OperatorLogDAO;
|
||||
import com.orion.ops.module.infra.define.operator.AuthenticationOperatorType;
|
||||
import com.orion.ops.module.infra.entity.domain.OperatorLogDO;
|
||||
import com.orion.ops.module.infra.entity.request.operator.OperatorLogQueryRequest;
|
||||
import com.orion.ops.module.infra.entity.vo.LoginHistoryVO;
|
||||
import com.orion.ops.module.infra.entity.vo.OperatorLogVO;
|
||||
import com.orion.ops.module.infra.service.OperatorLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志 服务实现类
|
||||
@@ -46,6 +50,19 @@ public class OperatorLogServiceImpl implements OperatorLogService {
|
||||
.dataGrid(OperatorLogConvert.MAPPER::to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LoginHistoryVO> getLoginHistory(String username) {
|
||||
// 条件
|
||||
OperatorLogQueryRequest request = new OperatorLogQueryRequest();
|
||||
request.setUsername(username);
|
||||
request.setType(AuthenticationOperatorType.LOGIN);
|
||||
LambdaQueryWrapper<OperatorLogDO> wrapper = this.buildQueryWrapper(request);
|
||||
// 查询
|
||||
return operatorLogDAO.of(wrapper)
|
||||
.limit(Const.LOGIN_HISTORY_COUNT)
|
||||
.list(OperatorLogConvert.MAPPER::toLoginHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询 wrapper
|
||||
*
|
||||
@@ -55,12 +72,14 @@ public class OperatorLogServiceImpl implements OperatorLogService {
|
||||
private LambdaQueryWrapper<OperatorLogDO> buildQueryWrapper(OperatorLogQueryRequest request) {
|
||||
return operatorLogDAO.wrapper()
|
||||
.eq(OperatorLogDO::getUserId, request.getUserId())
|
||||
.eq(OperatorLogDO::getUsername, request.getUsername())
|
||||
.eq(OperatorLogDO::getRiskLevel, request.getRiskLevel())
|
||||
.eq(OperatorLogDO::getModule, request.getModule())
|
||||
.eq(OperatorLogDO::getType, request.getType())
|
||||
.eq(OperatorLogDO::getResult, request.getResult())
|
||||
.ge(OperatorLogDO::getStartTime, request.getStartTimeStart())
|
||||
.le(OperatorLogDO::getStartTime, request.getStartTimeEnd());
|
||||
.le(OperatorLogDO::getStartTime, request.getStartTimeEnd())
|
||||
.orderByDesc(OperatorLogDO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public class SystemUserServiceImpl implements SystemUserService {
|
||||
// 更新用户
|
||||
int effect = systemUserDAO.updateById(updateRecord);
|
||||
log.info("SystemUserService-updateUserStatus effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
|
||||
// 如果之前是锁定则删除登陆失败次数缓存
|
||||
// 如果之前是锁定则删除登录失败次数缓存
|
||||
if (UserStatusEnum.LOCKED.getStatus().equals(record.getStatus())) {
|
||||
redisTemplate.delete(UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(record.getUsername()));
|
||||
}
|
||||
@@ -224,9 +224,9 @@ public class SystemUserServiceImpl implements SystemUserService {
|
||||
update.setPassword(Signatures.md5(request.getPassword()));
|
||||
int effect = systemUserDAO.updateById(update);
|
||||
log.info("SystemUserService-resetPassword record: {}, effect: {}", JSON.toJSONString(update), effect);
|
||||
// 删除登陆失败次数缓存
|
||||
// 删除登录失败次数缓存
|
||||
redisTemplate.delete(UserCacheKeyDefine.LOGIN_FAILED_COUNT.format(record.getUsername()));
|
||||
// 删除登陆缓存
|
||||
// 删除登录缓存
|
||||
String loginKey = UserCacheKeyDefine.LOGIN_TOKEN.format(id, "*");
|
||||
Set<String> loginKeyList = RedisUtils.scanKeys(loginKey);
|
||||
if (!loginKeyList.isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user