新增登录日志功能

This commit is contained in:
阿沐 2022-08-28 00:02:00 +08:00
parent 16f0ba8771
commit 9e515b1d62
14 changed files with 648 additions and 70 deletions

View File

@ -270,48 +270,6 @@ COMMENT ON COLUMN sys_role_data_scope.create_time IS '创建时间';
COMMENT ON COLUMN sys_role_data_scope.updater IS '更新者';
COMMENT ON COLUMN sys_role_data_scope.update_time IS '更新时间';
CREATE TABLE sys_oauth_client (
id bigint IDENTITY NOT NULL,
client_id varchar(256),
client_secret varchar(256),
resource_ids varchar(256),
scope varchar(256),
authorized_grant_types varchar(256),
web_server_redirect_uri varchar(256),
authorities varchar(256),
access_token_validity int,
refresh_token_validity int,
additional_information varchar(4096),
autoapprove varchar(128),
version int,
deleted int,
creator bigint,
create_time datetime,
updater bigint,
update_time datetime,
primary key (id)
);
COMMENT ON TABLE sys_oauth_client IS '客户端管理';
COMMENT ON COLUMN sys_oauth_client.id IS 'id';
COMMENT ON COLUMN sys_oauth_client.client_id IS '客户端id';
COMMENT ON COLUMN sys_oauth_client.client_secret IS '客户端密钥';
COMMENT ON COLUMN sys_oauth_client.resource_ids IS '资源ids';
COMMENT ON COLUMN sys_oauth_client.scope IS '授权范围';
COMMENT ON COLUMN sys_oauth_client.authorized_grant_types IS '授权类型';
COMMENT ON COLUMN sys_oauth_client.web_server_redirect_uri IS '回调地址';
COMMENT ON COLUMN sys_oauth_client.authorities IS '回调地址';
COMMENT ON COLUMN sys_oauth_client.access_token_validity IS '访问令牌有效期';
COMMENT ON COLUMN sys_oauth_client.refresh_token_validity IS '刷新令牌有效期';
COMMENT ON COLUMN sys_oauth_client.additional_information IS '附加信息';
COMMENT ON COLUMN sys_oauth_client.autoapprove IS '自动授权';
COMMENT ON COLUMN sys_oauth_client.version IS '版本号';
COMMENT ON COLUMN sys_oauth_client.deleted IS '删除标识 0正常 1已删除';
COMMENT ON COLUMN sys_oauth_client.creator IS '创建者';
COMMENT ON COLUMN sys_oauth_client.create_time IS '创建时间';
COMMENT ON COLUMN sys_oauth_client.updater IS '更新者';
COMMENT ON COLUMN sys_oauth_client.update_time IS '更新时间';
create table sys_dict_type
(
id bigint IDENTITY NOT NULL,
@ -372,13 +330,34 @@ COMMENT ON COLUMN sys_dict_data.create_time IS '创建时间';
COMMENT ON COLUMN sys_dict_data.updater IS '更新者';
COMMENT ON COLUMN sys_dict_data.update_time IS '更新时间';
create table sys_log_login
(
id bigint IDENTITY NOT NULL,
username varchar(50),
ip varchar(32),
address varchar(32),
user_agent varchar(500),
status int,
operation int,
create_time datetime,
primary key (id)
);
COMMENT ON TABLE sys_log_login IS '登录日志';
COMMENT ON COLUMN sys_log_login.id IS 'id';
COMMENT ON COLUMN sys_log_login.username IS '用户名';
COMMENT ON COLUMN sys_log_login.ip IS '登录IP';
COMMENT ON COLUMN sys_log_login.address IS '登录地点';
COMMENT ON COLUMN sys_log_login.user_agent IS 'User Agent';
COMMENT ON COLUMN sys_log_login.status IS '登录状态 0失败 1成功';
COMMENT ON COLUMN sys_log_login.operation IS '操作信息 0登录成功 1退出成功 2验证码错误 3账号密码错误';
COMMENT ON COLUMN sys_log_login.create_time IS '创建时间';
SET IDENTITY_INSERT sys_user ON;
INSERT INTO sys_user (id, username, password, real_name, avatar, gender, email, mobile, status, org_id, super_admin, version, deleted, creator, create_time, updater, update_time) VALUES (10000, 'admin', '{bcrypt}$2a$10$mW/yJPHjyueQ1g26WNBz0uxVPa0GQdJO1fFZmqdkqgMTGnyszlXxu', 'admin', 'https://cdn.maku.net/images/avatar.png', 0, 'babamu@126.com', '13612345678', 1, null, 1, 0, 0, 10000, now(), 10000, now());
SET IDENTITY_INSERT sys_oauth_client ON;
INSERT INTO sys_oauth_client (id, client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, version, deleted, creator, create_time, updater, update_time) VALUES (1, 'web', '123456', '', 'all', '["authorization_code","password","implicit","client_credentials","refresh_token"]', 'https://gitee.com/makunet', NULL, 43200, 604800, NULL, 'true', 0, 0, 10000, now(), 10000, now());
SET IDENTITY_INSERT sys_menu ON;
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (1, 0, '系统设置', NULL, NULL, 0, 0, 'icon-setting', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (2, 1, '菜单管理', 'sys/menu/index', NULL, 0, 0, 'icon-menu', 0, 0, 0, 10000, now(), 10000, now());

View File

@ -153,28 +153,6 @@ create table sys_role_data_scope
key idx_role_id (role_id)
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT ='角色数据权限';
CREATE TABLE sys_oauth_client (
id bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
client_id varchar(256) NOT NULL COMMENT '客户端id',
client_secret varchar(256) COMMENT '客户端密钥',
resource_ids varchar(256) COMMENT '资源ids',
scope varchar(256) COMMENT '授权范围',
authorized_grant_types varchar(256) COMMENT '授权类型',
web_server_redirect_uri varchar(256) COMMENT '回调地址',
authorities varchar(256) COMMENT '权限标识',
access_token_validity int COMMENT '访问令牌有效期',
refresh_token_validity int COMMENT '刷新令牌有效期',
additional_information varchar(4096) COMMENT '附加信息',
autoapprove varchar(128) COMMENT '自动授权',
version int COMMENT '版本号',
deleted tinyint COMMENT '删除标识 0正常 1已删除',
creator bigint COMMENT '创建者',
create_time datetime COMMENT '创建时间',
updater bigint COMMENT '更新者',
update_time datetime COMMENT '更新时间',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='客户端管理';
create table sys_dict_type
(
id bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
@ -225,9 +203,22 @@ create table sys_attachment
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT ='附件管理';
create table sys_log_login
(
id bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
username varchar(50) NOT NULL COMMENT '用户名',
ip varchar(32) COMMENT '登录IP',
address varchar(32) COMMENT '登录地点',
user_agent varchar(500) COMMENT 'User Agent',
status tinyint COMMENT '登录状态 0失败 1成功',
operation tinyint unsigned COMMENT '操作信息 0登录成功 1退出成功 2验证码错误 3账号密码错误',
create_time datetime COMMENT '创建时间',
primary key (id)
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT ='登录日志';
INSERT INTO sys_user (id, username, password, real_name, avatar, gender, email, mobile, status, org_id, super_admin, version, deleted, creator, create_time, updater, update_time) VALUES (10000, 'admin', '{bcrypt}$2a$10$mW/yJPHjyueQ1g26WNBz0uxVPa0GQdJO1fFZmqdkqgMTGnyszlXxu', 'admin', 'https://cdn.maku.net/images/avatar.png', 0, 'babamu@126.com', '13612345678', 1, null, 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_oauth_client (id, client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, version, deleted, creator, create_time, updater, update_time) VALUES (1, 'web', '123456', '', 'all', '["authorization_code","password","implicit","client_credentials","refresh_token"]', 'https://gitee.com/makunet', NULL, 43200, 604800, NULL, 'true', 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (1, 0, '系统设置', NULL, NULL, 0, 0, 'icon-setting', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (2, 1, '菜单管理', 'sys/menu/index', NULL, 0, 0, 'icon-menu', 0, 0, 0, 10000, now(), 10000, now());
@ -241,12 +232,12 @@ INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sor
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (10, 7, '修改', '', 'sys:dict:update,sys:dict:info', 1, 0, '', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (11, 7, '删除', '', 'sys:dict:delete', 1, 0, '', 3, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (12, 0, '权限管理', '', '', 0, 0, 'icon-safetycertificate', 0, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (13, 12, '岗位管理', 'sys/post/index', '', 0, 0, 'icon-addteam', 2, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (13, 12, '岗位管理', 'sys/post/index', '', 0, 0, 'icon-solution', 2, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (14, 13, '查询', '', 'sys:post:page', 1, 0, '', 0, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (15, 13, '新增', '', 'sys:post:save', 1, 0, '', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (16, 13, '修改', '', 'sys:post:update,sys:post:info', 1, 0, '', 2, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (17, 13, '删除', '', 'sys:post:delete', 1, 0, '', 3, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (18, 12, '机构管理', 'sys/org/index', '', 0, 0, 'icon-team', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (18, 12, '机构管理', 'sys/org/index', '', 0, 0, 'icon-cluster', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (19, 18, '查询', '', 'sys:org:list', 1, 0, '', 0, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (20, 18, '新增', '', 'sys:org:save', 1, 0, '', 1, 0, 0, 10000, now(), 10000, now());
INSERT INTO sys_menu (id, pid, name, url, authority, type, open_style, icon, sort, version, deleted, creator, create_time, updater, update_time) VALUES (21, 18, '修改', '', 'sys:org:update,sys:org:info', 1, 0, '', 2, 0, 0, 10000, now(), 10000, now());

View File

@ -0,0 +1,39 @@
package net.maku.system.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import net.maku.framework.common.page.PageResult;
import net.maku.framework.common.utils.Result;
import net.maku.system.query.SysLogLoginQuery;
import net.maku.system.service.SysLogLoginService;
import net.maku.system.vo.SysLogLoginVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@RestController
@RequestMapping("sys/log/login")
@Tag(name = "登录日志")
@AllArgsConstructor
public class SysLogLoginController {
private final SysLogLoginService sysLogLoginService;
@GetMapping("page")
@Operation(summary = "分页")
@PreAuthorize("hasAuthority('sys:log:login')")
public Result<PageResult<SysLogLoginVO>> page(@Valid SysLogLoginQuery query) {
PageResult<SysLogLoginVO> page = sysLogLoginService.page(query);
return Result.ok(page);
}
}

View File

@ -0,0 +1,25 @@
package net.maku.system.convert;
import net.maku.system.entity.SysLogLoginEntity;
import net.maku.system.vo.SysLogLoginVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@Mapper
public interface SysLogLoginConvert {
SysLogLoginConvert INSTANCE = Mappers.getMapper(SysLogLoginConvert.class);
SysLogLoginEntity convert(SysLogLoginVO vo);
SysLogLoginVO convert(SysLogLoginEntity entity);
List<SysLogLoginVO> convertList(List<SysLogLoginEntity> list);
}

View File

@ -0,0 +1,15 @@
package net.maku.system.dao;
import net.maku.framework.common.dao.BaseDao;
import net.maku.system.entity.SysLogLoginEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@Mapper
public interface SysLogLoginDao extends BaseDao<SysLogLoginEntity> {
}

View File

@ -0,0 +1,61 @@
package net.maku.system.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@Data
@TableName("sys_log_login")
public class SysLogLoginEntity {
/**
* id
*/
@TableId
private Long id;
/**
* 用户名
*/
private String username;
/**
* 登录IP
*/
private String ip;
/**
* 登录地点
*/
private String address;
/**
* User Agent
*/
private String userAgent;
/**
* 登录状态 0失败 1成功
*/
private Integer status;
/**
* 操作信息 0登录成功 1退出成功 2验证码错误 3账号密码错误
*/
private Integer operation;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
}

View File

@ -0,0 +1,32 @@
package net.maku.system.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 登录信息
*
* @author 阿沐 babamu@126.com
*/
@Getter
@AllArgsConstructor
public enum LoginOperationEnum {
/**
* 登录成功
*/
LOGIN_SUCCESS(0),
/**
* 退出成功
*/
LOGOUT_SUCCESS(1),
/**
* 验证码错误
*/
CAPTCHA_FAIL(2),
/**
* 账号密码错误
*/
ACCOUNT_FAIL(3);
private final int value;
}

View File

@ -0,0 +1,26 @@
package net.maku.system.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.maku.framework.common.query.Query;
/**
* 登录日志查询
*
* @author 阿沐 babamu@126.com
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(description = "登录日志查询")
public class SysLogLoginQuery extends Query {
@Schema(description = "用户名")
private String username;
@Schema(description = "登录地点")
private String address;
@Schema(description = "登录状态 0失败 1成功")
private Integer status;
}

View File

@ -0,0 +1,26 @@
package net.maku.system.service;
import net.maku.framework.common.page.PageResult;
import net.maku.framework.common.service.BaseService;
import net.maku.system.entity.SysLogLoginEntity;
import net.maku.system.query.SysLogLoginQuery;
import net.maku.system.vo.SysLogLoginVO;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
public interface SysLogLoginService extends BaseService<SysLogLoginEntity> {
PageResult<SysLogLoginVO> page(SysLogLoginQuery query);
/**
* 保存登录日志
*
* @param username 用户名
* @param status 登录状态
* @param operation 操作信息
*/
void save(String username, Integer status, Integer operation);
}

View File

@ -0,0 +1,69 @@
package net.maku.system.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import net.maku.framework.common.page.PageResult;
import net.maku.framework.common.service.impl.BaseServiceImpl;
import net.maku.framework.common.utils.AddressUtils;
import net.maku.framework.common.utils.HttpContextUtils;
import net.maku.framework.common.utils.IpUtils;
import net.maku.system.convert.SysLogLoginConvert;
import net.maku.system.dao.SysLogLoginDao;
import net.maku.system.entity.SysLogLoginEntity;
import net.maku.system.query.SysLogLoginQuery;
import net.maku.system.service.SysLogLoginService;
import net.maku.system.vo.SysLogLoginVO;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@Service
@AllArgsConstructor
public class SysLogLoginServiceImpl extends BaseServiceImpl<SysLogLoginDao, SysLogLoginEntity> implements SysLogLoginService {
@Override
public PageResult<SysLogLoginVO> page(SysLogLoginQuery query) {
IPage<SysLogLoginEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
return new PageResult<>(SysLogLoginConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
}
private LambdaQueryWrapper<SysLogLoginEntity> getWrapper(SysLogLoginQuery query) {
LambdaQueryWrapper<SysLogLoginEntity> wrapper = Wrappers.lambdaQuery();
wrapper.like(StrUtil.isNotBlank(query.getUsername()), SysLogLoginEntity::getUsername, query.getUsername());
wrapper.like(StrUtil.isNotBlank(query.getAddress()), SysLogLoginEntity::getAddress, query.getAddress());
wrapper.like(query.getStatus() != null, SysLogLoginEntity::getStatus, query.getStatus());
wrapper.orderByDesc(SysLogLoginEntity::getId);
return wrapper;
}
@Override
public void save(String username, Integer status, Integer operation) {
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
assert request != null;
String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
String ip = IpUtils.getIpAddr(request);
String address = AddressUtils.getAddressByIP(ip);
SysLogLoginEntity entity = new SysLogLoginEntity();
entity.setUsername(username);
entity.setStatus(status);
entity.setOperation(operation);
entity.setIp(ip);
entity.setAddress(address);
entity.setUserAgent(userAgent);
baseMapper.insert(entity);
}
}

View File

@ -0,0 +1,46 @@
package net.maku.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import net.maku.framework.common.utils.DateUtils;
import java.io.Serializable;
import java.util.Date;
/**
* 登录日志
*
* @author 阿沐 babamu@126.com
*/
@Data
@Schema(description = "登录日志")
public class SysLogLoginVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "登录IP")
private String ip;
@Schema(description = "登录地点")
private String address;
@Schema(description = "User Agent")
private String userAgent;
@Schema(description = "登录状态 0失败 1成功")
private Integer status;
@Schema(description = "操作信息 0登录成功 1退出成功 2验证码错误 3账号密码错误")
private Integer operation;
@Schema(description = "创建时间")
@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
private Date createTime;
}

View File

@ -0,0 +1,6 @@
<?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="net.maku.system.dao.SysLogLoginDao">
</mapper>

View File

@ -0,0 +1,58 @@
package net.maku.framework.common.utils;
import cn.hutool.http.HttpUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 获取真实地址
*
* @author 阿沐 babamu@126.com
*/
@Slf4j
public class AddressUtils {
// 实时查询
public static final String ADDRESS_URL = "https://whois.pconline.com.cn/ipJson.jsp";
public static final String UNKNOWN = "未知";
public static String getAddressByIP(String ip) {
// 内网
if (IpUtils.internalIp(ip)) {
return "内网IP";
}
try {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("ip", ip);
paramMap.put("json", true);
String response = HttpUtil.get(ADDRESS_URL, paramMap);
if (StringUtils.isBlank(response)) {
log.error("根据IP获取地址异常 {}", ip);
return UNKNOWN;
}
Address address = JsonUtils.parseObject(response, Address.class);
return String.format("%s %s", address.getPro(), address.getCity());
} catch (Exception e) {
log.error("根据IP获取地址异常 {}", ip);
}
return UNKNOWN;
}
@Data
static class Address {
/**
*
*/
private String pro;
/**
*
*/
private String city;
}
}

View File

@ -0,0 +1,205 @@
package net.maku.framework.common.utils;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* IP地址 工具类
*
* @author 阿沐 babamu@126.com
*/
public class IpUtils {
/**
* 获取客户端IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
}
/**
* 检查是否为内部IP地址
*
* @param ip IP地址
*/
public static boolean internalIp(String ip) {
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
/**
* 检查是否为内部IP地址
*
* @param addr byte地址
*/
private static boolean internalIp(byte[] addr) {
if (addr == null || addr.length < 2) {
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
if (b1 == SECTION_6) {
return true;
}
default:
return false;
}
}
/**
* 将IPv4地址转换成字节
*
* @param text IPv4地址
* @return byte 字节
*/
public static byte[] textToNumericFormatV4(String text) {
if (text.length() == 0) {
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try {
long l;
int i;
switch (elements.length) {
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
} catch (NumberFormatException e) {
return null;
}
return bytes;
}
/**
* 获取本地IP地址
*
* @return 本地IP地址
*/
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException ignored) {
}
return "127.0.0.1";
}
/**
* 获取主机名
*
* @return 本地主机名
*/
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ignored) {
}
return "未知";
}
/**
* 从反向代理中获得第一个非 unknown IP地址
*/
public static String getMultistageReverseProxyIp(String ip) {
// 反向代理检测
if (ip.indexOf(",") > 0) {
final String[] ips = ip.trim().split(",");
for (String sub : ips) {
if (!"unknown".equalsIgnoreCase(sub)) {
ip = sub;
break;
}
}
}
return ip;
}
}