diff --git a/pom.xml b/pom.xml
index 2d6927e..2d18bc8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -275,6 +275,11 @@
hutool-core
5.5.9
+
+ cn.hutool
+ hutool-http
+ 5.5.9
+
diff --git a/src/main/java/com/rymcu/forest/core/service/log/VisitAspect.java b/src/main/java/com/rymcu/forest/core/service/log/VisitAspect.java
index 809e7ff..ce0ed4f 100644
--- a/src/main/java/com/rymcu/forest/core/service/log/VisitAspect.java
+++ b/src/main/java/com/rymcu/forest/core/service/log/VisitAspect.java
@@ -59,12 +59,13 @@ public class VisitAspect {
String url = request.getRequestURL().toString();
String ua = request.getHeader("user-agent");
String referer = request.getHeader("Referer");
+ String fingerprint = request.getHeader("fingerprint");
Visit visit = new Visit();
visit.setVisitUrl(url);
visit.setVisitIp(ip);
visit.setVisitUa(ua);
visit.setVisitCity("");
- visit.setVisitDeviceId("");
+ visit.setVisitDeviceId(fingerprint);
visit.setVisitRefererUrl(referer);
visit.setCreatedTime(new Date());
String authHeader = request.getHeader(JwtConstants.AUTHORIZATION);
diff --git a/src/main/java/com/rymcu/forest/entity/LoginRecord.java b/src/main/java/com/rymcu/forest/entity/LoginRecord.java
new file mode 100644
index 0000000..36825cd
--- /dev/null
+++ b/src/main/java/com/rymcu/forest/entity/LoginRecord.java
@@ -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;
+
+}
diff --git a/src/main/java/com/rymcu/forest/mapper/LoginRecordMapper.java b/src/main/java/com/rymcu/forest/mapper/LoginRecordMapper.java
new file mode 100644
index 0000000..400d4c9
--- /dev/null
+++ b/src/main/java/com/rymcu/forest/mapper/LoginRecordMapper.java
@@ -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 {
+}
diff --git a/src/main/java/com/rymcu/forest/service/LoginRecordService.java b/src/main/java/com/rymcu/forest/service/LoginRecordService.java
new file mode 100644
index 0000000..0ef3fc8
--- /dev/null
+++ b/src/main/java/com/rymcu/forest/service/LoginRecordService.java
@@ -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 {
+ /**
+ * 保存登录记录
+ * @param idUser
+ * @return
+ */
+ LoginRecord saveLoginRecord(Integer idUser);
+}
diff --git a/src/main/java/com/rymcu/forest/service/impl/LoginRecordServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/LoginRecordServiceImpl.java
new file mode 100644
index 0000000..60ab7bb
--- /dev/null
+++ b/src/main/java/com/rymcu/forest/service/impl/LoginRecordServiceImpl.java
@@ -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 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;
+ }
+}
diff --git a/src/main/java/com/rymcu/forest/service/impl/UserServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/UserServiceImpl.java
index 013522e..bc2d4a1 100644
--- a/src/main/java/com/rymcu/forest/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/rymcu/forest/service/impl/UserServiceImpl.java
@@ -13,6 +13,7 @@ import com.rymcu.forest.lucene.util.UserIndexUtil;
import com.rymcu.forest.mapper.RoleMapper;
import com.rymcu.forest.mapper.UserExtendMapper;
import com.rymcu.forest.mapper.UserMapper;
+import com.rymcu.forest.service.LoginRecordService;
import com.rymcu.forest.service.UserService;
import com.rymcu.forest.util.BeanCopierUtil;
import com.rymcu.forest.util.Utils;
@@ -42,6 +43,8 @@ public class UserServiceImpl extends AbstractService implements UserServic
private TokenManager tokenManager;
@Resource
private UserExtendMapper userExtendMapper;
+ @Resource
+ private LoginRecordService loginRecordService;
private final static String AVATAR_SVG_TYPE = "1";
private final static String DEFAULT_AVATAR = "https://static.rymcu.com/article/1578475481946.png";
@@ -112,7 +115,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public Map login(String account, String password) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
User user = userMapper.findByAccount(account);
if (user != null) {
if (Utils.comparePwd(password, user.getPassword())) {
@@ -123,6 +126,8 @@ public class UserServiceImpl extends AbstractService implements UserServic
tokenUser.setToken(tokenManager.createToken(account));
tokenUser.setWeights(userMapper.selectRoleWeightsByUser(user.getIdUser()));
map.put("user", tokenUser);
+ // 保存登录日志
+ loginRecordService.saveLoginRecord(tokenUser.getIdUser());
} else {
map.put("message", "密码错误!");
}
@@ -134,8 +139,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public UserDTO findUserDTOByAccount(String account) {
- UserDTO user = userMapper.selectUserDTOByAccount(account);
- return user;
+ return userMapper.selectUserDTOByAccount(account);
}
@Override
@@ -155,7 +159,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
@Transactional(rollbackFor = Exception.class)
public Map updateUserRole(Integer idUser, Integer idRole) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
Integer result = userMapper.updateUserRole(idUser, idRole);
if (result == 0) {
map.put("message", "更新失败!");
@@ -166,7 +170,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
@Transactional(rollbackFor = Exception.class)
public Map updateStatus(Integer idUser, String status) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
Integer result = userMapper.updateStatus(idUser, status);
if (result == 0) {
map.put("message", "更新失败!");
@@ -176,7 +180,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public Map findUserInfo(Integer idUser) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
UserInfoDTO user = userMapper.selectUserInfo(idUser);
if (user == null) {
map.put("message", "用户不存在!");
@@ -196,7 +200,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
@Transactional(rollbackFor = Exception.class)
public Map updateUserInfo(UserInfoDTO user) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
user.setNickname(formatNickname(user.getNickname()));
Integer number = userMapper.checkNicknameByIdUser(user.getIdUser(), user.getNickname());
if (number > 0) {
@@ -228,7 +232,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public Map checkNickname(Integer idUser, String nickname) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
Integer number = userMapper.checkNicknameByIdUser(idUser, nickname);
if (number > 0) {
map.put("message", "该昵称已使用!");
@@ -248,7 +252,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public Map updateUserExtend(UserExtend userExtend) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
int result = userExtendMapper.updateByPrimaryKeySelective(userExtend);
if (result == 0) {
map.put("message", "操作失败!");
@@ -283,7 +287,7 @@ public class UserServiceImpl extends AbstractService implements UserServic
@Override
public Map updatePassword(UpdatePasswordDTO updatePasswordDTO) {
- Map map = new HashMap(1);
+ Map map = new HashMap(2);
String password = Utils.entryptPassword(updatePasswordDTO.getPassword());
userMapper.updatePasswordById(updatePasswordDTO.getIdUser(), password);
map.put("message", "更新成功!");
diff --git a/src/main/java/com/rymcu/forest/util/UserUtils.java b/src/main/java/com/rymcu/forest/util/UserUtils.java
index 6899270..2343060 100644
--- a/src/main/java/com/rymcu/forest/util/UserUtils.java
+++ b/src/main/java/com/rymcu/forest/util/UserUtils.java
@@ -25,6 +25,7 @@ public class UserUtils {
/**
* 通过token获取当前用户的信息
+ *
* @return
*/
public static User getCurrentUserByToken() throws BaseApiException {
@@ -52,7 +53,7 @@ public class UserUtils {
}
public static TokenUser getTokenUser(String token) {
- if(StringUtils.isNotBlank(token)){
+ if (StringUtils.isNotBlank(token)) {
// 验证token
Claims claims;
try {
@@ -65,7 +66,7 @@ public class UserUtils {
TokenModel model = tokenManager.getToken(token, account.toString());
if (tokenManager.checkToken(model)) {
User user = userMapper.findByAccount(account.toString());
- if(user != null){
+ if (user != null) {
TokenUser tokenUser = new TokenUser();
BeanCopierUtil.copy(user, tokenUser);
tokenUser.setToken(token);
diff --git a/src/main/java/mapper/LoginRecordMapper.xml b/src/main/java/mapper/LoginRecordMapper.xml
new file mode 100644
index 0000000..fcf529f
--- /dev/null
+++ b/src/main/java/mapper/LoginRecordMapper.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file