用户登录记录

1.  用户登录记录
2.  浏览器指纹
This commit is contained in:
ronger 2022-01-14 10:44:56 +08:00 committed by GitHub
commit 079df3af88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 166 additions and 13 deletions

View File

@ -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>

View File

@ -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);

View 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;
}

View 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> {
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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", "更新成功!");

View File

@ -25,6 +25,7 @@ public class UserUtils {
/** /**
* 通过token获取当前用户的信息 * 通过token获取当前用户的信息
*
* @return * @return
*/ */
public static User getCurrentUserByToken() throws BaseApiException { public static User getCurrentUserByToken() throws BaseApiException {
@ -52,7 +53,7 @@ public class UserUtils {
} }
public static TokenUser getTokenUser(String token) { public static TokenUser getTokenUser(String token) {
if(StringUtils.isNotBlank(token)){ if (StringUtils.isNotBlank(token)) {
// 验证token // 验证token
Claims claims; Claims claims;
try { try {
@ -65,7 +66,7 @@ public class UserUtils {
TokenModel model = tokenManager.getToken(token, account.toString()); TokenModel model = tokenManager.getToken(token, account.toString());
if (tokenManager.checkToken(model)) { if (tokenManager.checkToken(model)) {
User user = userMapper.findByAccount(account.toString()); User user = userMapper.findByAccount(account.toString());
if(user != null){ if (user != null) {
TokenUser tokenUser = new TokenUser(); TokenUser tokenUser = new TokenUser();
BeanCopierUtil.copy(user, tokenUser); BeanCopierUtil.copy(user, tokenUser);
tokenUser.setToken(token); tokenUser.setToken(token);

View 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>