在无人机应用方向,因为提供试用,所以为了防止客户在试用时恶意传播账号,我们必须要记录用户的登录ip以及归属地。在登录模块,我们经常要记录登录日志,其中比较重要的信息有ip地址和ip归属地。
本文我将从我们的系统中划分出来一个简单的小功能:登录日志。
让我们直接开始!
一、说在前面
因为本身系统很庞大,加上代码的隐私性,我这边不会介绍非常多的属性,不过我能保证的是,代码你抄上去肯定能用。
二、数据库设计
按照开发流程,首先肯定是数据库的设计,我这边直接给出数据库建表语句:
CREATE TABLE `login_log` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(255) DEFAULT NULL COMMENT '登陆人姓名',`ip` varchar(255) DEFAULT NULL COMMENT '登录ip',`ip_attribution` varchar(255) DEFAULT NULL COMMENT 'ip归属地信息',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `login_log` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) DEFAULT NULL COMMENT '登陆人姓名', `ip` varchar(255) DEFAULT NULL COMMENT '登录ip', `ip_attribution` varchar(255) DEFAULT NULL COMMENT 'ip归属地信息', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `login_log` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) DEFAULT NULL COMMENT '登陆人姓名', `ip` varchar(255) DEFAULT NULL COMMENT '登录ip', `ip_attribution` varchar(255) DEFAULT NULL COMMENT 'ip归属地信息', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
在建表前,请保证你的数据库是创建好的,这个前提有点搞笑了。
由表可以看到,我们创建了login_log表,即登录日志表,字段名有id(主键)、name(登陆人姓名)、ip(登录ip)、ip_attribution(ip归属地信息)、create_time(创建时间)。
在真实的企业环境中,登录日志肯定远远不止这些,我是从我们的表中挑出了最基本的字段,像ip所属经纬度,因为需要调用第三方服务,我这边没有展示,当然市面上也有开源的根据ip获取经纬度的库,只不过不准确,想要准确还是要购买第三方服务。
三、代码编写
3.1 框架选型
我选用的框架是:
- SpringBoot:2.7.0
- jdk:1.8
- mybatis-plus:3.4.2
- lombok:1.18.22
还有其他基础的到时候报红的时候自行解决。
3.2 pom 依赖
跟ip归属地相关的依赖:
<dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>1.7.2</version></dependency><dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>1.7.2</version> </dependency><dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>1.7.2</version> </dependency>
跟加载ip归属地数据库文件的依赖:
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency><dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency><dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
3.3 实体类
LoginLogEntity:
package com.wljlsmz.transitcenter.model.entity;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import java.time.LocalDateTime;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: 用户登录日志实体类*/@Data@Builder@AllArgsConstructor@NoArgsConstructor@TableName("login_log")public class LoginLogEntity {/*** 主键*/@TableId(type = IdType.AUTO)private Integer id;/*** 登陆人姓名*/@TableField("name")private String name;/*** 登录ip*/@TableField("ip")private String ip;/*** ip归属地信息*/@TableField("ip_attribution")private String ipAttribution;/*** 创建时间*/@TableField("create_time")private LocalDateTime createTime;}package com.wljlsmz.transitcenter.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 用户登录日志实体类 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("login_log") public class LoginLogEntity { /** * 主键 */ @TableId(type = IdType.AUTO) private Integer id; /** * 登陆人姓名 */ @TableField("name") private String name; /** * 登录ip */ @TableField("ip") private String ip; /** * ip归属地信息 */ @TableField("ip_attribution") private String ipAttribution; /** * 创建时间 */ @TableField("create_time") private LocalDateTime createTime; }package com.wljlsmz.transitcenter.model.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 用户登录日志实体类 */ @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("login_log") public class LoginLogEntity { /** * 主键 */ @TableId(type = IdType.AUTO) private Integer id; /** * 登陆人姓名 */ @TableField("name") private String name; /** * 登录ip */ @TableField("ip") private String ip; /** * ip归属地信息 */ @TableField("ip_attribution") private String ipAttribution; /** * 创建时间 */ @TableField("create_time") private LocalDateTime createTime; }
3.4 Mapper类
LoginLogMapper:
package com.wljlsmz.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.wljlsmz.transitcenter.model.entity.LoginLogEntity;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: 登录日志mapper接口类*/public interface LoginLogMapper extends BaseMapper<LoginLogEntity> {}package com.wljlsmz.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.wljlsmz.transitcenter.model.entity.LoginLogEntity; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志mapper接口类 */ public interface LoginLogMapper extends BaseMapper<LoginLogEntity> { }package com.wljlsmz.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.wljlsmz.transitcenter.model.entity.LoginLogEntity; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志mapper接口类 */ public interface LoginLogMapper extends BaseMapper<LoginLogEntity> { }
3.5 service类
ILoginLogService:
package com.wljlsmz.transitcenter.service;import com.wljlsmz.transitcenter.model.dto.LoginLogDTO;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: 登录日志服务接口类*/public interface ILoginLogService {int saveLoginLog(LoginLogDTO loginLogDTO);}package com.wljlsmz.transitcenter.service; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志服务接口类 */ public interface ILoginLogService { int saveLoginLog(LoginLogDTO loginLogDTO); }package com.wljlsmz.transitcenter.service; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志服务接口类 */ public interface ILoginLogService { int saveLoginLog(LoginLogDTO loginLogDTO); }
LoginLogServiceImpl:
package com.wljlsmz.transitcenter.service.impl;import com.wljlsmz.transitcenter.mapper.LoginLogMapper;import com.wljlsmz.transitcenter.model.dto.LoginLogDTO;import com.wljlsmz.transitcenter.model.entity.LoginLogEntity;import com.wljlsmz.transitcenter.service.ILoginLogService;import com.wljlsmz.transitcenter.util.CopyUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.time.LocalDateTime;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: 登录日志服务接口实现类*/@Servicepublic class LoginLogServiceImpl implements ILoginLogService {@Autowiredprivate LoginLogMapper mapper;@Overridepublic int saveLoginLog(LoginLogDTO loginLogDTO) {LoginLogEntity loginLogEntity = CopyUtil.copy(loginLogDTO, LoginLogEntity.class);loginLogEntity.setCreateTime(LocalDateTime.now());return mapper.insert(loginLogEntity);}}package com.wljlsmz.transitcenter.service.impl; import com.wljlsmz.transitcenter.mapper.LoginLogMapper; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; import com.wljlsmz.transitcenter.model.entity.LoginLogEntity; import com.wljlsmz.transitcenter.service.ILoginLogService; import com.wljlsmz.transitcenter.util.CopyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志服务接口实现类 */ @Service public class LoginLogServiceImpl implements ILoginLogService { @Autowired private LoginLogMapper mapper; @Override public int saveLoginLog(LoginLogDTO loginLogDTO) { LoginLogEntity loginLogEntity = CopyUtil.copy(loginLogDTO, LoginLogEntity.class); loginLogEntity.setCreateTime(LocalDateTime.now()); return mapper.insert(loginLogEntity); } }package com.wljlsmz.transitcenter.service.impl; import com.wljlsmz.transitcenter.mapper.LoginLogMapper; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; import com.wljlsmz.transitcenter.model.entity.LoginLogEntity; import com.wljlsmz.transitcenter.service.ILoginLogService; import com.wljlsmz.transitcenter.util.CopyUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDateTime; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 登录日志服务接口实现类 */ @Service public class LoginLogServiceImpl implements ILoginLogService { @Autowired private LoginLogMapper mapper; @Override public int saveLoginLog(LoginLogDTO loginLogDTO) { LoginLogEntity loginLogEntity = CopyUtil.copy(loginLogDTO, LoginLogEntity.class); loginLogEntity.setCreateTime(LocalDateTime.now()); return mapper.insert(loginLogEntity); } }
3.6 IP工具类
IpUtils:
package com.wljlsmz.transitcenter.util;import org.apache.commons.io.FileUtils;import org.apache.commons.lang3.StringUtils;import org.lionsoul.ip2region.DataBlock;import org.lionsoul.ip2region.DbConfig;import org.lionsoul.ip2region.DbSearcher;import org.lionsoul.ip2region.Util;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import java.io.File;import java.io.InputStream;import javax.servlet.http.HttpServletRequest;import lombok.extern.slf4j.Slf4j;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: ip工具类*/@Slf4jpublic class IpUtils {/*** 本地环回地址*/private static final String LOCAL_IP = "127.0.0.1";/*** 未知*/private static final String UNKNOWN = "unknown";public static String getIpAddr(HttpServletRequest request) {if (request == null) {return UNKNOWN;}String ip = request.getHeader("x-forwarded-for");if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("X-Forwarded-For");}if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getHeader("X-Real-IP");}if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip;}public static String getCityInfo(String ip) throws Exception {if (!Util.isIpAddress(ip)) {log.error("错误: 无效的ip地址");return null;}InputStream is = new PathMatchingResourcePatternResolver().getResources("ip2region.db")[0].getInputStream();File target = new File("ip2region.db");FileUtils.copyInputStreamToFile(is, target);is.close();if (StringUtils.isEmpty(String.valueOf(target))) {log.error("错误: 无效的ip2region.db文件");return null;}DbSearcher searcher = new DbSearcher(new DbConfig(), String.valueOf(target));try {DataBlock dataBlock = (DataBlock) searcher.getClass().getMethod("btreeSearch", String.class).invoke(searcher, ip);String ipInfo = dataBlock.getRegion();if (!StringUtils.isEmpty(ipInfo)) {ipInfo = ipInfo.replace("|0", "");ipInfo = ipInfo.replace("0|", "");}return ipInfo;} catch (Exception e) {e.printStackTrace();}return null;}}package com.wljlsmz.transitcenter.util; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.lionsoul.ip2region.DataBlock; import org.lionsoul.ip2region.DbConfig; import org.lionsoul.ip2region.DbSearcher; import org.lionsoul.ip2region.Util; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.File; import java.io.InputStream; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: ip工具类 */ @Slf4j public class IpUtils { /** * 本地环回地址 */ private static final String LOCAL_IP = "127.0.0.1"; /** * 未知 */ private static final String UNKNOWN = "unknown"; public static String getIpAddr(HttpServletRequest request) { if (request == null) { return UNKNOWN; } String ip = request.getHeader("x-forwarded-for"); if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip; } public static String getCityInfo(String ip) throws Exception { if (!Util.isIpAddress(ip)) { log.error("错误: 无效的ip地址"); return null; } InputStream is = new PathMatchingResourcePatternResolver().getResources("ip2region.db")[0].getInputStream(); File target = new File("ip2region.db"); FileUtils.copyInputStreamToFile(is, target); is.close(); if (StringUtils.isEmpty(String.valueOf(target))) { log.error("错误: 无效的ip2region.db文件"); return null; } DbSearcher searcher = new DbSearcher(new DbConfig(), String.valueOf(target)); try { DataBlock dataBlock = (DataBlock) searcher.getClass().getMethod("btreeSearch", String.class).invoke(searcher, ip); String ipInfo = dataBlock.getRegion(); if (!StringUtils.isEmpty(ipInfo)) { ipInfo = ipInfo.replace("|0", ""); ipInfo = ipInfo.replace("0|", ""); } return ipInfo; } catch (Exception e) { e.printStackTrace(); } return null; } }package com.wljlsmz.transitcenter.util; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.lionsoul.ip2region.DataBlock; import org.lionsoul.ip2region.DbConfig; import org.lionsoul.ip2region.DbSearcher; import org.lionsoul.ip2region.Util; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.File; import java.io.InputStream; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: ip工具类 */ @Slf4j public class IpUtils { /** * 本地环回地址 */ private static final String LOCAL_IP = "127.0.0.1"; /** * 未知 */ private static final String UNKNOWN = "unknown"; public static String getIpAddr(HttpServletRequest request) { if (request == null) { return UNKNOWN; } String ip = request.getHeader("x-forwarded-for"); if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return "0:0:0:0:0:0:0:1".equals(ip) ? LOCAL_IP : ip; } public static String getCityInfo(String ip) throws Exception { if (!Util.isIpAddress(ip)) { log.error("错误: 无效的ip地址"); return null; } InputStream is = new PathMatchingResourcePatternResolver().getResources("ip2region.db")[0].getInputStream(); File target = new File("ip2region.db"); FileUtils.copyInputStreamToFile(is, target); is.close(); if (StringUtils.isEmpty(String.valueOf(target))) { log.error("错误: 无效的ip2region.db文件"); return null; } DbSearcher searcher = new DbSearcher(new DbConfig(), String.valueOf(target)); try { DataBlock dataBlock = (DataBlock) searcher.getClass().getMethod("btreeSearch", String.class).invoke(searcher, ip); String ipInfo = dataBlock.getRegion(); if (!StringUtils.isEmpty(ipInfo)) { ipInfo = ipInfo.replace("|0", ""); ipInfo = ipInfo.replace("0|", ""); } return ipInfo; } catch (Exception e) { e.printStackTrace(); } return null; } }
上诉代码中提到了ip2region.db文件,这个文件需要放到resources目录下:
![如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息? 图片[1]-如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息?-不念博客](https://www.bunian.cn/wp-content/uploads/2022/11/image-276.png)
ip2region.db文件我放在网盘中,大家可以按需下载:
链接:https://pan.quark.cn/s/372c8f12c8b4提取码:2Kyy链接:https://pan.quark.cn/s/372c8f12c8b4 提取码:2Kyy链接:https://pan.quark.cn/s/372c8f12c8b4 提取码:2Kyy
点击下载即可:
![如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息? 图片[2]-如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息?-不念博客](https://www.bunian.cn/wp-content/uploads/2022/11/image-277.png)
3.7 Controller类
这个类就使用到了以上所有的准备代码:
UserController:
package com.wljlsmz.transitcenter.controller;import com.wljlsmz.transitcenter.common.response.ResponseResult;import com.wljlsmz.transitcenter.model.dto.LoginDTO;import com.wljlsmz.transitcenter.model.dto.LoginLogDTO;import com.wljlsmz.transitcenter.service.ILoginLogService;import com.wljlsmz.transitcenter.service.IUserService;import com.wljlsmz.transitcenter.util.IpUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import io.swagger.annotations.ApiParam;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;import lombok.extern.slf4j.Slf4j;/*** @author: wljlsmz* @date: 2022/11/15 10:28* @description: 用户接口类*/@RestController@Slf4j@Api(tags = "用户接口")@RequestMapping("${url.user.prefix}${url.user.version}")public class UserController {@Autowiredprivate IUserService userService;@Autowiredprivate ILoginLogService loginLogService;@ApiOperation("登录")@PostMapping("login")public ResponseResult login(@ApiParam @RequestBody LoginDTO loginDTO, HttpServletRequest request) {String ip = IpUtils.getIpAddr(request);String cityInfo = null;try {cityInfo = IpUtils.getCityInfo(ip);} catch (Exception e) {log.error("获取ip归属地信息失败!");}loginLogService.saveLoginLog(LoginLogDTO.builder().ip(ip).ipAttribution(cityInfo).name(loginDTO.getUserName()).build());return userService.login(loginDTO);}}package com.wljlsmz.transitcenter.controller; import com.wljlsmz.transitcenter.common.response.ResponseResult; import com.wljlsmz.transitcenter.model.dto.LoginDTO; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; import com.wljlsmz.transitcenter.service.ILoginLogService; import com.wljlsmz.transitcenter.service.IUserService; import com.wljlsmz.transitcenter.util.IpUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 用户接口类 */ @RestController @Slf4j @Api(tags = "用户接口") @RequestMapping("${url.user.prefix}${url.user.version}") public class UserController { @Autowired private IUserService userService; @Autowired private ILoginLogService loginLogService; @ApiOperation("登录") @PostMapping("login") public ResponseResult login(@ApiParam @RequestBody LoginDTO loginDTO, HttpServletRequest request) { String ip = IpUtils.getIpAddr(request); String cityInfo = null; try { cityInfo = IpUtils.getCityInfo(ip); } catch (Exception e) { log.error("获取ip归属地信息失败!"); } loginLogService.saveLoginLog( LoginLogDTO.builder() .ip(ip) .ipAttribution(cityInfo) .name(loginDTO.getUserName()) .build()); return userService.login(loginDTO); } }package com.wljlsmz.transitcenter.controller; import com.wljlsmz.transitcenter.common.response.ResponseResult; import com.wljlsmz.transitcenter.model.dto.LoginDTO; import com.wljlsmz.transitcenter.model.dto.LoginLogDTO; import com.wljlsmz.transitcenter.service.ILoginLogService; import com.wljlsmz.transitcenter.service.IUserService; import com.wljlsmz.transitcenter.util.IpUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; /** * @author: wljlsmz * @date: 2022/11/15 10:28 * @description: 用户接口类 */ @RestController @Slf4j @Api(tags = "用户接口") @RequestMapping("${url.user.prefix}${url.user.version}") public class UserController { @Autowired private IUserService userService; @Autowired private ILoginLogService loginLogService; @ApiOperation("登录") @PostMapping("login") public ResponseResult login(@ApiParam @RequestBody LoginDTO loginDTO, HttpServletRequest request) { String ip = IpUtils.getIpAddr(request); String cityInfo = null; try { cityInfo = IpUtils.getCityInfo(ip); } catch (Exception e) { log.error("获取ip归属地信息失败!"); } loginLogService.saveLoginLog( LoginLogDTO.builder() .ip(ip) .ipAttribution(cityInfo) .name(loginDTO.getUserName()) .build()); return userService.login(loginDTO); } }
以上代码被我删减了好多,其实大家在使用的时候,值需要把下面这段代码摘出来放到自己的测试代码中即可:
String ip = IpUtils.getIpAddr(request);String cityInfo = null;try {cityInfo = IpUtils.getCityInfo(ip);} catch (Exception e) {log.error("获取ip归属地信息失败!");}loginLogService.saveLoginLog(LoginLogDTO.builder().ip(ip).ipAttribution(cityInfo).name(loginDTO.getUserName()).build());String ip = IpUtils.getIpAddr(request); String cityInfo = null; try { cityInfo = IpUtils.getCityInfo(ip); } catch (Exception e) { log.error("获取ip归属地信息失败!"); } loginLogService.saveLoginLog( LoginLogDTO.builder() .ip(ip) .ipAttribution(cityInfo) .name(loginDTO.getUserName()) .build());String ip = IpUtils.getIpAddr(request); String cityInfo = null; try { cityInfo = IpUtils.getCityInfo(ip); } catch (Exception e) { log.error("获取ip归属地信息失败!"); } loginLogService.saveLoginLog( LoginLogDTO.builder() .ip(ip) .ipAttribution(cityInfo) .name(loginDTO.getUserName()) .build());
测试代码
我们用swagger测试一下接口:
![如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息? 图片[3]-如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息?-不念博客](https://www.bunian.cn/wp-content/uploads/2022/11/716.jpeg)
测试成功后,我们看下数据库:
![如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息? 图片[4]-如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息?-不念博客](https://www.bunian.cn/wp-content/uploads/2022/11/image-278.png)
成功记录了ip信息,在真实的企业环境中,你也再增加一些字段。
至此代码全部演示完毕。
总结
本文主要介绍了如何在登录接口增加登录日志的记录,文中的代码大家可以参考,有任何问题可以在下方评论区与不念讨论。