获取客户端的访问记录(待验证)
参考:https://cloud.tencent.com/developer/article/2233415 如何在SpringBoot项目中,实现记录用户登录的IP地址及归属地信息?
https://blog.csdn.net/a254124185/article/details/117294692 微服务获取真实请求的IP
(1)springboot获取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;
选用框架
SpringBoot:2.7.0
jdk:1.8
mybatis-plus:3.4.2
lombok:1.18.22
1.1依赖
#跟ip归属地相关的依赖:
<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>
1.2实体类
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;
}
Mapper类
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> {
}
service类
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.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);
}
}
ip工具类
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目录下
链接:https://pan.baidu.com/s/1KizC6hftNlC7STjSzPYUlA
提取码:0aqk
controller类
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);
}
}
2.微服务获取ip地址
2.1nginx
http {
include mime.types;
default_type application/octet-stream;
upstream gwadds {
server 127.0.0.1:81;
}
server {
listen 80;
server_name gw.com;
location / {
proxy_pass http://gwadds/;
#重构请求头,获取客户端请求的IP地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
2.2网管过滤器中获取
@Component
public class GatewayFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // nginx 会从请求头中设置 客户端的真实ip放入网关
String sourceIp = exchange.getRequest().getHeaders().getFirst("X-Real-IP");
if (StringUtils.isEmpty(sourceIp)) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.BAD_REQUEST);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "500");
jsonObject.put("msg", "sourceIp is null");
DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getByt es());
return response.writeWith(Mono.just(buffer));
}// 使用网关过滤
return chain.filter(exchange);
}
}
2.3微服务中获取
@RestController
@RequestMapping("/member")
public class MemberController {
@PostMapping("/login")
BaseResponse<JSONObject> login(@RequestBody UserLoginDto userLoginDto,
@RequestHeader("X-Real-IP") String sourceIp,
@RequestHeader("channel") String channel,
@RequestHeader("deviceInfor") String deviceInfor);
}
本文作者:spiderMan1-1
本文链接:https://www.cnblogs.com/cgy1995/p/17571648.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
java工具类
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步