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