✨ 用户登录记录
1. ✨ 用户登录记录 2. ✨ 浏览器指纹
This commit is contained in:
commit
079df3af88
5
pom.xml
5
pom.xml
@ -275,6 +275,11 @@
|
|||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
<version>5.5.9</version>
|
<version>5.5.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-http</artifactId>
|
||||||
|
<version>5.5.9</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -59,12 +59,13 @@ public class VisitAspect {
|
|||||||
String url = request.getRequestURL().toString();
|
String url = request.getRequestURL().toString();
|
||||||
String ua = request.getHeader("user-agent");
|
String ua = request.getHeader("user-agent");
|
||||||
String referer = request.getHeader("Referer");
|
String referer = request.getHeader("Referer");
|
||||||
|
String fingerprint = request.getHeader("fingerprint");
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
visit.setVisitUrl(url);
|
visit.setVisitUrl(url);
|
||||||
visit.setVisitIp(ip);
|
visit.setVisitIp(ip);
|
||||||
visit.setVisitUa(ua);
|
visit.setVisitUa(ua);
|
||||||
visit.setVisitCity("");
|
visit.setVisitCity("");
|
||||||
visit.setVisitDeviceId("");
|
visit.setVisitDeviceId(fingerprint);
|
||||||
visit.setVisitRefererUrl(referer);
|
visit.setVisitRefererUrl(referer);
|
||||||
visit.setCreatedTime(new Date());
|
visit.setCreatedTime(new Date());
|
||||||
String authHeader = request.getHeader(JwtConstants.AUTHORIZATION);
|
String authHeader = request.getHeader(JwtConstants.AUTHORIZATION);
|
||||||
|
52
src/main/java/com/rymcu/forest/entity/LoginRecord.java
Normal file
52
src/main/java/com/rymcu/forest/entity/LoginRecord.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package com.rymcu.forest.entity;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录记录表
|
||||||
|
* @author ronger
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Table(name="forest_login_record")
|
||||||
|
public class LoginRecord implements Serializable,Cloneable {
|
||||||
|
|
||||||
|
/** 主键 */
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "JDBC")
|
||||||
|
@Column(name = "id")
|
||||||
|
private Integer id;
|
||||||
|
/** IP */
|
||||||
|
@Column(name = "login_ip")
|
||||||
|
private String loginIp;
|
||||||
|
/** User-Agent */
|
||||||
|
@Column(name = "login_ua")
|
||||||
|
private String loginUa;
|
||||||
|
/** 城市 */
|
||||||
|
@Column(name = "login_city")
|
||||||
|
private String loginCity;
|
||||||
|
/** 设备唯一标识 */
|
||||||
|
@Column(name = "login_device_id")
|
||||||
|
private String loginDeviceId;
|
||||||
|
/** 设备操作系统 */
|
||||||
|
@Column(name = "login_os")
|
||||||
|
private String loginOS;
|
||||||
|
/** 设备浏览器 */
|
||||||
|
@Column(name = "login_browser")
|
||||||
|
private String loginBrowser;
|
||||||
|
/** 用户 id */
|
||||||
|
@Column(name = "id_user")
|
||||||
|
private Integer idUser;
|
||||||
|
/** 创建时间 */
|
||||||
|
@Column(name = "created_time")
|
||||||
|
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createdTime;
|
||||||
|
|
||||||
|
}
|
14
src/main/java/com/rymcu/forest/mapper/LoginRecordMapper.java
Normal file
14
src/main/java/com/rymcu/forest/mapper/LoginRecordMapper.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.rymcu.forest.mapper;
|
||||||
|
|
||||||
|
import com.rymcu.forest.core.mapper.Mapper;
|
||||||
|
import com.rymcu.forest.entity.LoginRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created on 2022/1/14 8:46.
|
||||||
|
*
|
||||||
|
* @author ronger
|
||||||
|
* @email ronger-x@outlook.com
|
||||||
|
* @packageName com.rymcu.forest.mapper
|
||||||
|
*/
|
||||||
|
public interface LoginRecordMapper extends Mapper<LoginRecord> {
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.rymcu.forest.service;
|
||||||
|
|
||||||
|
import com.rymcu.forest.core.service.Service;
|
||||||
|
import com.rymcu.forest.entity.LoginRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created on 2022/1/14 8:47.
|
||||||
|
*
|
||||||
|
* @author ronger
|
||||||
|
* @email ronger-x@outlook.com
|
||||||
|
* @packageName com.rymcu.forest.service
|
||||||
|
*/
|
||||||
|
public interface LoginRecordService extends Service<LoginRecord> {
|
||||||
|
/**
|
||||||
|
* 保存登录记录
|
||||||
|
* @param idUser
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
LoginRecord saveLoginRecord(Integer idUser);
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.rymcu.forest.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
|
import com.rymcu.forest.core.service.AbstractService;
|
||||||
|
import com.rymcu.forest.entity.LoginRecord;
|
||||||
|
import com.rymcu.forest.mapper.LoginRecordMapper;
|
||||||
|
import com.rymcu.forest.service.LoginRecordService;
|
||||||
|
import com.rymcu.forest.util.Utils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created on 2022/1/14 8:48.
|
||||||
|
*
|
||||||
|
* @author ronger
|
||||||
|
* @email ronger-x@outlook.com
|
||||||
|
* @packageName com.rymcu.forest.service.impl
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class LoginRecordServiceImpl extends AbstractService<LoginRecord> implements LoginRecordService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LoginRecordMapper loginRecordMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public LoginRecord saveLoginRecord(Integer idUser) {
|
||||||
|
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||||
|
String ip = Utils.getIpAddress(request);
|
||||||
|
String ua = request.getHeader("user-agent");
|
||||||
|
String fingerprint = request.getHeader("fingerprint");
|
||||||
|
LoginRecord loginRecord = new LoginRecord();
|
||||||
|
loginRecord.setIdUser(idUser);
|
||||||
|
loginRecord.setLoginIp(ip);
|
||||||
|
loginRecord.setLoginUa(ua);
|
||||||
|
loginRecord.setLoginDeviceId(fingerprint);
|
||||||
|
UserAgent userAgent = UserAgentUtil.parse(ua);
|
||||||
|
loginRecord.setLoginOS(userAgent.getOs().toString());
|
||||||
|
loginRecord.setLoginBrowser(userAgent.getBrowser().toString());
|
||||||
|
loginRecord.setCreatedTime(new Date());
|
||||||
|
loginRecordMapper.insertSelective(loginRecord);
|
||||||
|
return loginRecord;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import com.rymcu.forest.lucene.util.UserIndexUtil;
|
|||||||
import com.rymcu.forest.mapper.RoleMapper;
|
import com.rymcu.forest.mapper.RoleMapper;
|
||||||
import com.rymcu.forest.mapper.UserExtendMapper;
|
import com.rymcu.forest.mapper.UserExtendMapper;
|
||||||
import com.rymcu.forest.mapper.UserMapper;
|
import com.rymcu.forest.mapper.UserMapper;
|
||||||
|
import com.rymcu.forest.service.LoginRecordService;
|
||||||
import com.rymcu.forest.service.UserService;
|
import com.rymcu.forest.service.UserService;
|
||||||
import com.rymcu.forest.util.BeanCopierUtil;
|
import com.rymcu.forest.util.BeanCopierUtil;
|
||||||
import com.rymcu.forest.util.Utils;
|
import com.rymcu.forest.util.Utils;
|
||||||
@ -42,6 +43,8 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
private TokenManager tokenManager;
|
private TokenManager tokenManager;
|
||||||
@Resource
|
@Resource
|
||||||
private UserExtendMapper userExtendMapper;
|
private UserExtendMapper userExtendMapper;
|
||||||
|
@Resource
|
||||||
|
private LoginRecordService loginRecordService;
|
||||||
|
|
||||||
private final static String AVATAR_SVG_TYPE = "1";
|
private final static String AVATAR_SVG_TYPE = "1";
|
||||||
private final static String DEFAULT_AVATAR = "https://static.rymcu.com/article/1578475481946.png";
|
private final static String DEFAULT_AVATAR = "https://static.rymcu.com/article/1578475481946.png";
|
||||||
@ -112,7 +115,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map login(String account, String password) {
|
public Map login(String account, String password) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
User user = userMapper.findByAccount(account);
|
User user = userMapper.findByAccount(account);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
if (Utils.comparePwd(password, user.getPassword())) {
|
if (Utils.comparePwd(password, user.getPassword())) {
|
||||||
@ -123,6 +126,8 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
tokenUser.setToken(tokenManager.createToken(account));
|
tokenUser.setToken(tokenManager.createToken(account));
|
||||||
tokenUser.setWeights(userMapper.selectRoleWeightsByUser(user.getIdUser()));
|
tokenUser.setWeights(userMapper.selectRoleWeightsByUser(user.getIdUser()));
|
||||||
map.put("user", tokenUser);
|
map.put("user", tokenUser);
|
||||||
|
// 保存登录日志
|
||||||
|
loginRecordService.saveLoginRecord(tokenUser.getIdUser());
|
||||||
} else {
|
} else {
|
||||||
map.put("message", "密码错误!");
|
map.put("message", "密码错误!");
|
||||||
}
|
}
|
||||||
@ -134,8 +139,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDTO findUserDTOByAccount(String account) {
|
public UserDTO findUserDTOByAccount(String account) {
|
||||||
UserDTO user = userMapper.selectUserDTOByAccount(account);
|
return userMapper.selectUserDTOByAccount(account);
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -155,7 +159,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Map updateUserRole(Integer idUser, Integer idRole) {
|
public Map updateUserRole(Integer idUser, Integer idRole) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
Integer result = userMapper.updateUserRole(idUser, idRole);
|
Integer result = userMapper.updateUserRole(idUser, idRole);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
map.put("message", "更新失败!");
|
map.put("message", "更新失败!");
|
||||||
@ -166,7 +170,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Map updateStatus(Integer idUser, String status) {
|
public Map updateStatus(Integer idUser, String status) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
Integer result = userMapper.updateStatus(idUser, status);
|
Integer result = userMapper.updateStatus(idUser, status);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
map.put("message", "更新失败!");
|
map.put("message", "更新失败!");
|
||||||
@ -176,7 +180,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map findUserInfo(Integer idUser) {
|
public Map findUserInfo(Integer idUser) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
UserInfoDTO user = userMapper.selectUserInfo(idUser);
|
UserInfoDTO user = userMapper.selectUserInfo(idUser);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
map.put("message", "用户不存在!");
|
map.put("message", "用户不存在!");
|
||||||
@ -196,7 +200,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Map updateUserInfo(UserInfoDTO user) {
|
public Map updateUserInfo(UserInfoDTO user) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
user.setNickname(formatNickname(user.getNickname()));
|
user.setNickname(formatNickname(user.getNickname()));
|
||||||
Integer number = userMapper.checkNicknameByIdUser(user.getIdUser(), user.getNickname());
|
Integer number = userMapper.checkNicknameByIdUser(user.getIdUser(), user.getNickname());
|
||||||
if (number > 0) {
|
if (number > 0) {
|
||||||
@ -228,7 +232,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map checkNickname(Integer idUser, String nickname) {
|
public Map checkNickname(Integer idUser, String nickname) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
Integer number = userMapper.checkNicknameByIdUser(idUser, nickname);
|
Integer number = userMapper.checkNicknameByIdUser(idUser, nickname);
|
||||||
if (number > 0) {
|
if (number > 0) {
|
||||||
map.put("message", "该昵称已使用!");
|
map.put("message", "该昵称已使用!");
|
||||||
@ -248,7 +252,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map updateUserExtend(UserExtend userExtend) {
|
public Map updateUserExtend(UserExtend userExtend) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
int result = userExtendMapper.updateByPrimaryKeySelective(userExtend);
|
int result = userExtendMapper.updateByPrimaryKeySelective(userExtend);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
map.put("message", "操作失败!");
|
map.put("message", "操作失败!");
|
||||||
@ -283,7 +287,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map updatePassword(UpdatePasswordDTO updatePasswordDTO) {
|
public Map updatePassword(UpdatePasswordDTO updatePasswordDTO) {
|
||||||
Map map = new HashMap(1);
|
Map map = new HashMap(2);
|
||||||
String password = Utils.entryptPassword(updatePasswordDTO.getPassword());
|
String password = Utils.entryptPassword(updatePasswordDTO.getPassword());
|
||||||
userMapper.updatePasswordById(updatePasswordDTO.getIdUser(), password);
|
userMapper.updatePasswordById(updatePasswordDTO.getIdUser(), password);
|
||||||
map.put("message", "更新成功!");
|
map.put("message", "更新成功!");
|
||||||
|
@ -25,6 +25,7 @@ public class UserUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过token获取当前用户的信息
|
* 通过token获取当前用户的信息
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static User getCurrentUserByToken() throws BaseApiException {
|
public static User getCurrentUserByToken() throws BaseApiException {
|
||||||
|
4
src/main/java/mapper/LoginRecordMapper.xml
Normal file
4
src/main/java/mapper/LoginRecordMapper.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?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.rymcu.forest.mapper.LoginRecordMapper">
|
||||||
|
</mapper>
|
Loading…
Reference in New Issue
Block a user