更新
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package com.vetti.hotake.mapper;
|
||||
|
||||
import com.vetti.hotake.domain.HotakeSecurityTrustedDevices;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 可信设备Mapper接口
|
||||
*
|
||||
* @author vetti
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
public interface HotakeSecurityTrustedDevicesMapper
|
||||
{
|
||||
/**
|
||||
* 查询可信设备
|
||||
*
|
||||
* @param id 可信设备主键
|
||||
* @return 可信设备
|
||||
*/
|
||||
public HotakeSecurityTrustedDevices selectHotakeSecurityTrustedDevicesById(Long id);
|
||||
|
||||
/**
|
||||
* 根据用户ID和设备ID查询可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备ID
|
||||
* @return 可信设备
|
||||
*/
|
||||
public HotakeSecurityTrustedDevices selectByUserIdAndDeviceId(@Param("userId") Long userId, @Param("deviceId") String deviceId);
|
||||
|
||||
/**
|
||||
* 查询可信设备列表
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 可信设备集合
|
||||
*/
|
||||
public List<HotakeSecurityTrustedDevices> selectHotakeSecurityTrustedDevicesList(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 查询用户的可信设备列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 可信设备集合
|
||||
*/
|
||||
public List<HotakeSecurityTrustedDevices> selectTrustedDevicesByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 新增可信设备
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertHotakeSecurityTrustedDevices(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 修改可信设备
|
||||
*
|
||||
* @param hotakeSecurityTrustedDevices 可信设备
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateHotakeSecurityTrustedDevices(HotakeSecurityTrustedDevices hotakeSecurityTrustedDevices);
|
||||
|
||||
/**
|
||||
* 删除可信设备
|
||||
*
|
||||
* @param id 可信设备主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityTrustedDevicesById(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除可信设备
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteHotakeSecurityTrustedDevicesByIds(Long[] ids);
|
||||
|
||||
/**
|
||||
* 移除用户的可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int removeTrustedDevice(@Param("id") Long id, @Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 清理过期的可信设备
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public int cleanExpiredTrustedDevices();
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.vetti.hotake.service;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySettings;
|
||||
import com.vetti.hotake.domain.dto.SecurityChangePasswordDto;
|
||||
import com.vetti.hotake.domain.vo.SecuritySessionVo;
|
||||
import com.vetti.hotake.domain.vo.SecurityTrustedDeviceVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -97,4 +98,37 @@ public interface IHotakeSecurityService
|
||||
* @return 结果
|
||||
*/
|
||||
int updateSessionLogout(String sessionToken);
|
||||
|
||||
/**
|
||||
* 获取当前用户的可信设备列表
|
||||
*
|
||||
* @return 可信设备列表
|
||||
*/
|
||||
List<SecurityTrustedDeviceVo> getTrustedDevices();
|
||||
|
||||
/**
|
||||
* 添加可信设备
|
||||
*
|
||||
* @param deviceId 设备唯一标识
|
||||
* @param deviceName 设备名称
|
||||
* @return 结果
|
||||
*/
|
||||
int addTrustedDevice(String deviceId, String deviceName);
|
||||
|
||||
/**
|
||||
* 移除可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @return 结果
|
||||
*/
|
||||
int removeTrustedDevice(Long id);
|
||||
|
||||
/**
|
||||
* 检查设备是否为可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备唯一标识
|
||||
* @return 是否可信
|
||||
*/
|
||||
boolean isTrustedDevice(Long userId, String deviceId);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,15 @@ import com.vetti.hotake.domain.HotakeSecurityLoginSessions;
|
||||
import com.vetti.hotake.domain.HotakeSecurityPasswordHistory;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySecurityLogs;
|
||||
import com.vetti.hotake.domain.HotakeSecuritySettings;
|
||||
import com.vetti.hotake.domain.HotakeSecurityTrustedDevices;
|
||||
import com.vetti.hotake.domain.dto.SecurityChangePasswordDto;
|
||||
import com.vetti.hotake.domain.vo.SecuritySessionVo;
|
||||
import com.vetti.hotake.domain.vo.SecurityTrustedDeviceVo;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityLoginSessionsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityPasswordHistoryMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecuritySecurityLogsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecuritySettingsMapper;
|
||||
import com.vetti.hotake.mapper.HotakeSecurityTrustedDevicesMapper;
|
||||
import com.vetti.hotake.service.IHotakeSecurityService;
|
||||
import com.vetti.system.service.ISysUserService;
|
||||
import eu.bitwalker.useragentutils.Browser;
|
||||
@@ -60,6 +63,9 @@ public class HotakeSecurityServiceImpl extends BaseServiceImpl implements IHotak
|
||||
@Autowired
|
||||
private HotakeSecuritySecurityLogsMapper securityLogsMapper;
|
||||
|
||||
@Autowired
|
||||
private HotakeSecurityTrustedDevicesMapper trustedDevicesMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@@ -451,4 +457,202 @@ public class HotakeSecurityServiceImpl extends BaseServiceImpl implements IHotak
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的可信设备列表
|
||||
*
|
||||
* @return 可信设备列表
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public List<SecurityTrustedDeviceVo> getTrustedDevices()
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 查询用户的可信设备
|
||||
List<HotakeSecurityTrustedDevices> devicesList = trustedDevicesMapper.selectTrustedDevicesByUserId(userId);
|
||||
|
||||
// 获取当前设备标识(可以从请求头或Cookie中获取)
|
||||
String currentDeviceId = getCurrentDeviceId();
|
||||
|
||||
// 转换为VO
|
||||
List<SecurityTrustedDeviceVo> voList = new ArrayList<>();
|
||||
for (HotakeSecurityTrustedDevices device : devicesList)
|
||||
{
|
||||
SecurityTrustedDeviceVo vo = new SecurityTrustedDeviceVo();
|
||||
vo.setId(device.getId());
|
||||
vo.setDeviceId(device.getDeviceId());
|
||||
vo.setDeviceName(device.getDeviceName());
|
||||
vo.setDeviceType(device.getDeviceType());
|
||||
vo.setBrowser(device.getBrowser());
|
||||
vo.setOs(device.getOs());
|
||||
vo.setIpAddress(device.getIpAddress());
|
||||
vo.setLocation(device.getLocation());
|
||||
vo.setTrustExpiresAt(device.getTrustExpiresAt());
|
||||
vo.setCreateTime(device.getCreateTime());
|
||||
vo.setIsCurrent(device.getDeviceId().equals(currentDeviceId));
|
||||
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
return voList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加可信设备
|
||||
*
|
||||
* @param deviceId 设备唯一标识
|
||||
* @param deviceName 设备名称
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int addTrustedDevice(String deviceId, String deviceName)
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 检查是否已存在
|
||||
HotakeSecurityTrustedDevices existDevice = trustedDevicesMapper.selectByUserIdAndDeviceId(userId, deviceId);
|
||||
if (existDevice != null)
|
||||
{
|
||||
// 已存在,更新信任状态
|
||||
existDevice.setIsTrusted(1);
|
||||
existDevice.setDeviceName(deviceName);
|
||||
// 设置信任过期时间(30天)
|
||||
existDevice.setTrustExpiresAt(new Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
|
||||
fill(FillTypeEnum.UPDATE.getCode(), existDevice);
|
||||
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_UPDATE",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10012") + ":" + deviceName, "SUCCESS");
|
||||
|
||||
return trustedDevicesMapper.updateHotakeSecurityTrustedDevices(existDevice);
|
||||
}
|
||||
|
||||
// 解析User-Agent
|
||||
String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||
UserAgent ua = UserAgent.parseUserAgentString(userAgent);
|
||||
Browser browser = ua.getBrowser();
|
||||
OperatingSystem os = ua.getOperatingSystem();
|
||||
|
||||
// 获取IP和位置
|
||||
String ipAddress = IpUtils.getIpAddr();
|
||||
String location = AddressUtils.getRealAddressByIP(ipAddress);
|
||||
|
||||
// 判断设备类型
|
||||
String deviceType = "Desktop";
|
||||
if (os.getDeviceType() != null)
|
||||
{
|
||||
deviceType = os.getDeviceType().getName();
|
||||
}
|
||||
|
||||
// 创建新的可信设备记录
|
||||
HotakeSecurityTrustedDevices device = new HotakeSecurityTrustedDevices();
|
||||
device.setUserId(userId);
|
||||
device.setDeviceId(deviceId);
|
||||
device.setDeviceName(StringUtils.isNotEmpty(deviceName) ? deviceName : browser.getName() + " / " + os.getName());
|
||||
device.setDeviceType(deviceType);
|
||||
device.setBrowser(browser.getName());
|
||||
device.setOs(os.getName());
|
||||
device.setIpAddress(ipAddress);
|
||||
device.setLocation(location);
|
||||
device.setIsTrusted(1);
|
||||
// 设置信任过期时间(30天)
|
||||
device.setTrustExpiresAt(new Date(System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000));
|
||||
|
||||
fill(FillTypeEnum.INSERT.getCode(), device);
|
||||
|
||||
// 记录安全日志
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_ADD",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10013") + ":" + device.getDeviceName(), "SUCCESS");
|
||||
|
||||
return trustedDevicesMapper.insertHotakeSecurityTrustedDevices(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除可信设备
|
||||
*
|
||||
* @param id 设备记录ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int removeTrustedDevice(Long id)
|
||||
{
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
|
||||
// 查询设备信息
|
||||
HotakeSecurityTrustedDevices device = trustedDevicesMapper.selectHotakeSecurityTrustedDevicesById(id);
|
||||
if (device == null || !device.getUserId().equals(userId))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.messageCustomize("HotakeSecurityServiceImpl10014"));
|
||||
}
|
||||
|
||||
// 删除设备
|
||||
int result = trustedDevicesMapper.removeTrustedDevice(id, userId);
|
||||
|
||||
// 记录安全日志
|
||||
recordSecurityLog(userId, "TRUSTED_DEVICE_REMOVE",
|
||||
MessageUtils.messageCustomize("HotakeSecurityServiceImpl10015") + ":" + device.getDeviceName(), "SUCCESS");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查设备是否为可信设备
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param deviceId 设备唯一标识
|
||||
* @return 是否可信
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public boolean isTrustedDevice(Long userId, String deviceId)
|
||||
{
|
||||
if (StringUtils.isEmpty(deviceId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HotakeSecurityTrustedDevices device = trustedDevicesMapper.selectByUserIdAndDeviceId(userId, deviceId);
|
||||
if (device == null || device.getIsTrusted() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否过期
|
||||
if (device.getTrustExpiresAt() != null && device.getTrustExpiresAt().before(new Date()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前设备标识
|
||||
* 可以从请求头或Cookie中获取,这里简单实现
|
||||
*/
|
||||
private String getCurrentDeviceId()
|
||||
{
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
// 优先从请求头获取
|
||||
String deviceId = request.getHeader("X-Device-Id");
|
||||
if (StringUtils.isEmpty(deviceId))
|
||||
{
|
||||
// 从Cookie获取
|
||||
javax.servlet.http.Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null)
|
||||
{
|
||||
for (javax.servlet.http.Cookie cookie : cookies)
|
||||
{
|
||||
if ("device_id".equals(cookie.getName()))
|
||||
{
|
||||
deviceId = cookie.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deviceId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.vetti.hotake.mapper.HotakeSecurityTrustedDevicesMapper">
|
||||
|
||||
<resultMap type="HotakeSecurityTrustedDevices" id="HotakeSecurityTrustedDevicesResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="userId" column="user_id" />
|
||||
<result property="deviceId" column="device_id" />
|
||||
<result property="deviceName" column="device_name" />
|
||||
<result property="deviceType" column="device_type" />
|
||||
<result property="browser" column="browser" />
|
||||
<result property="os" column="os" />
|
||||
<result property="ipAddress" column="ip_address" />
|
||||
<result property="location" column="location" />
|
||||
<result property="isTrusted" column="is_trusted" />
|
||||
<result property="trustExpiresAt" column="trust_expires_at"/>
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="remark" column="remark" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectHotakeSecurityTrustedDevicesVo">
|
||||
select id, user_id, device_id, device_name, device_type, browser, os, ip_address, location, is_trusted, trust_expires_at, create_by, create_time, update_by, update_time, remark from hotake_security_trusted_devices
|
||||
</sql>
|
||||
|
||||
<select id="selectHotakeSecurityTrustedDevicesList" parameterType="HotakeSecurityTrustedDevices" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
<where>
|
||||
<if test="userId != null "> and user_id = #{userId}</if>
|
||||
<if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
|
||||
<if test="deviceName != null and deviceName != ''"> and device_name like concat('%', #{deviceName}, '%')</if>
|
||||
<if test="deviceType != null and deviceType != ''"> and device_type = #{deviceType}</if>
|
||||
<if test="browser != null and browser != ''"> and browser = #{browser}</if>
|
||||
<if test="os != null and os != ''"> and os = #{os}</if>
|
||||
<if test="isTrusted != null "> and is_trusted = #{isTrusted}</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<select id="selectHotakeSecurityTrustedDevicesById" parameterType="Long" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectByUserIdAndDeviceId" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where user_id = #{userId} and device_id = #{deviceId}
|
||||
</select>
|
||||
|
||||
<select id="selectTrustedDevicesByUserId" parameterType="Long" resultMap="HotakeSecurityTrustedDevicesResult">
|
||||
<include refid="selectHotakeSecurityTrustedDevicesVo"/>
|
||||
where user_id = #{userId} and is_trusted = 1 and (trust_expires_at is null or trust_expires_at > now())
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<insert id="insertHotakeSecurityTrustedDevices" parameterType="HotakeSecurityTrustedDevices" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into hotake_security_trusted_devices
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">user_id,</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id,</if>
|
||||
<if test="deviceName != null">device_name,</if>
|
||||
<if test="deviceType != null">device_type,</if>
|
||||
<if test="browser != null">browser,</if>
|
||||
<if test="os != null">os,</if>
|
||||
<if test="ipAddress != null">ip_address,</if>
|
||||
<if test="location != null">location,</if>
|
||||
<if test="isTrusted != null">is_trusted,</if>
|
||||
<if test="trustExpiresAt != null">trust_expires_at,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="remark != null">remark,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="userId != null">#{userId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">#{deviceId},</if>
|
||||
<if test="deviceName != null">#{deviceName},</if>
|
||||
<if test="deviceType != null">#{deviceType},</if>
|
||||
<if test="browser != null">#{browser},</if>
|
||||
<if test="os != null">#{os},</if>
|
||||
<if test="ipAddress != null">#{ipAddress},</if>
|
||||
<if test="location != null">#{location},</if>
|
||||
<if test="isTrusted != null">#{isTrusted},</if>
|
||||
<if test="trustExpiresAt != null">#{trustExpiresAt},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="remark != null">#{remark},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateHotakeSecurityTrustedDevices" parameterType="HotakeSecurityTrustedDevices">
|
||||
update hotake_security_trusted_devices
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="userId != null">user_id = #{userId},</if>
|
||||
<if test="deviceId != null and deviceId != ''">device_id = #{deviceId},</if>
|
||||
<if test="deviceName != null">device_name = #{deviceName},</if>
|
||||
<if test="deviceType != null">device_type = #{deviceType},</if>
|
||||
<if test="browser != null">browser = #{browser},</if>
|
||||
<if test="os != null">os = #{os},</if>
|
||||
<if test="ipAddress != null">ip_address = #{ipAddress},</if>
|
||||
<if test="location != null">location = #{location},</if>
|
||||
<if test="isTrusted != null">is_trusted = #{isTrusted},</if>
|
||||
<if test="trustExpiresAt != null">trust_expires_at = #{trustExpiresAt},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteHotakeSecurityTrustedDevicesById" parameterType="Long">
|
||||
delete from hotake_security_trusted_devices where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteHotakeSecurityTrustedDevicesByIds" parameterType="String">
|
||||
delete from hotake_security_trusted_devices where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<delete id="removeTrustedDevice">
|
||||
delete from hotake_security_trusted_devices where id = #{id} and user_id = #{userId}
|
||||
</delete>
|
||||
|
||||
<delete id="cleanExpiredTrustedDevices">
|
||||
delete from hotake_security_trusted_devices where trust_expires_at is not null and trust_expires_at < now()
|
||||
</delete>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user