Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-api-boot
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-api-boot
Commits
1704ab90
提交
1704ab90
authored
6月 20, 2024
作者:
方治民
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 新增 LoginLog 记录用户登录日志、使用 ip2region 解析登录 IP 信息等相关实现
上级
7eba35ac
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
297 行增加
和
69 行删除
+297
-69
build.gradle
basic-auth/build.gradle
+2
-0
LoginLog.java
...th/src/main/java/com/yiring/auth/domain/log/LoginLog.java
+66
-0
LoginLogRepository.java
...n/java/com/yiring/auth/domain/log/LoginLogRepository.java
+13
-0
AuthController.java
...rc/main/java/com/yiring/auth/web/auth/AuthController.java
+85
-27
build.gradle
basic-common/core/build.gradle
+1
-0
RateLimiterAspect.java
...main/java/com/yiring/common/aspect/RateLimiterAspect.java
+2
-2
RequestAspect.java
...src/main/java/com/yiring/common/aspect/RequestAspect.java
+2
-2
build.gradle
basic-common/util/build.gradle
+3
-0
ObjectMappingSerializer.java
...va/com/yiring/common/jackson/ObjectMappingSerializer.java
+2
-2
Commons.java
...on/util/src/main/java/com/yiring/common/util/Commons.java
+0
-36
IpUtil.java
...mon/util/src/main/java/com/yiring/common/util/IpUtil.java
+115
-0
README.md
basic-common/util/src/main/resources/ipdb/README.md
+4
-0
ip2region.xdb
basic-common/util/src/main/resources/ipdb/ip2region.xdb
+0
-0
build.gradle
build.gradle
+2
-0
没有找到文件。
basic-auth/build.gradle
浏览文件 @
1704ab90
...
@@ -4,6 +4,7 @@ plugins {
...
@@ -4,6 +4,7 @@ plugins {
dependencies
{
dependencies
{
implementation
project
(
':basic-common:core'
)
implementation
project
(
':basic-common:core'
)
implementation
project
(
':basic-common:i18n'
)
implementation
project
(
':basic-common:util'
)
implementation
project
(
':basic-common:util'
)
implementation
'org.springframework.boot:spring-boot-starter-data-jpa'
implementation
'org.springframework.boot:spring-boot-starter-data-jpa'
...
@@ -23,6 +24,7 @@ dependencies {
...
@@ -23,6 +24,7 @@ dependencies {
// hutool-core
// hutool-core
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-http:${hutoolVersion}"
// https://github.com/vladmihalcea/hypersistence-utils
// https://github.com/vladmihalcea/hypersistence-utils
// hypersistence-utils-hibernate-63
// hypersistence-utils-hibernate-63
...
...
basic-auth/src/main/java/com/yiring/auth/domain/log/LoginLog.java
0 → 100644
浏览文件 @
1704ab90
/* (C) 2024 YiRing, Inc. */
package
com
.
yiring
.
auth
.
domain
.
log
;
import
com.yiring.common.domain.BasicEntity
;
import
jakarta.persistence.Entity
;
import
jakarta.persistence.Table
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
lombok.*
;
import
lombok.experimental.FieldDefaults
;
import
lombok.experimental.FieldNameConstants
;
import
lombok.experimental.SuperBuilder
;
import
org.hibernate.annotations.Comment
;
import
org.hibernate.annotations.SQLDelete
;
import
org.hibernate.annotations.SQLRestriction
;
/**
* @author Jim
*/
@Getter
@Setter
@SuperBuilder
(
toBuilder
=
true
)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@SQLDelete
(
sql
=
LoginLog
.
DELETE_SQL
+
BasicEntity
.
Where
.
WHERE_ID
)
@SQLRestriction
(
BasicEntity
.
Where
.
EXIST
)
@Entity
@Table
(
name
=
LoginLog
.
TABLE_NAME
)
@Comment
(
"系统用户登录日志"
)
public
class
LoginLog
extends
BasicEntity
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
-
3979598668491115376L
;
public
static
final
String
TABLE_NAME
=
"SYS_LOGIN_LOG"
;
public
static
final
String
DELETE_SQL
=
"update "
+
TABLE_NAME
+
BasicEntity
.
Where
.
DELETE_SET
;
@Comment
(
"登录账号"
)
String
account
;
@Comment
(
"登录IP地址"
)
String
ip
;
@Comment
(
"登录地点"
)
String
location
;
@Comment
(
"User-Agent"
)
String
ua
;
@Comment
(
"操作系统"
)
String
os
;
@Comment
(
"平台"
)
String
platform
;
@Comment
(
"浏览器"
)
String
browser
;
@Comment
(
"登录状态"
)
Boolean
status
;
@Comment
(
"登录消息"
)
String
msg
;
}
basic-auth/src/main/java/com/yiring/auth/domain/log/LoginLogRepository.java
0 → 100644
浏览文件 @
1704ab90
/* (C) 2024 YiRing, Inc. */
package
com
.
yiring
.
auth
.
domain
.
log
;
import
java.io.Serializable
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.stereotype.Repository
;
/**
* @author ifzm
* 2024/6/20 17:53
*/
@Repository
public
interface
LoginLogRepository
extends
JpaRepository
<
LoginLog
,
Serializable
>
{}
basic-auth/src/main/java/com/yiring/auth/web/auth/AuthController.java
浏览文件 @
1704ab90
...
@@ -5,7 +5,10 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
...
@@ -5,7 +5,10 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
import
cn.dev33.satoken.secure.SaSecureUtil
;
import
cn.dev33.satoken.secure.SaSecureUtil
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.dev33.satoken.stp.StpUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.useragent.*
;
import
com.github.xiaoymin.knife4j.annotations.ApiSupport
;
import
com.github.xiaoymin.knife4j.annotations.ApiSupport
;
import
com.yiring.auth.domain.log.LoginLog
;
import
com.yiring.auth.domain.log.LoginLogRepository
;
import
com.yiring.auth.domain.user.User
;
import
com.yiring.auth.domain.user.User
;
import
com.yiring.auth.domain.user.UserRepository
;
import
com.yiring.auth.domain.user.UserRepository
;
import
com.yiring.auth.param.auth.LoginParam
;
import
com.yiring.auth.param.auth.LoginParam
;
...
@@ -14,13 +17,16 @@ import com.yiring.auth.param.auth.SafeParam;
...
@@ -14,13 +17,16 @@ import com.yiring.auth.param.auth.SafeParam;
import
com.yiring.auth.util.Auths
;
import
com.yiring.auth.util.Auths
;
import
com.yiring.auth.vo.auth.LoginVo
;
import
com.yiring.auth.vo.auth.LoginVo
;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.core.I18n
;
import
com.yiring.common.core.Result
;
import
com.yiring.common.core.Result
;
import
com.yiring.common.core.Status
;
import
com.yiring.common.exception.BusinessException
;
import
com.yiring.common.exception.BusinessException
;
import
com.yiring.common.util.
Commons
;
import
com.yiring.common.util.
IpUtil
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
jakarta.servlet.http.HttpServletRequest
;
import
jakarta.servlet.http.HttpServletRequest
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.util.Objects
;
import
lombok.RequiredArgsConstructor
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springdoc.core.annotations.ParameterObject
;
import
org.springdoc.core.annotations.ParameterObject
;
...
@@ -48,8 +54,10 @@ import org.springframework.web.bind.annotation.RestController;
...
@@ -48,8 +54,10 @@ import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RequiredArgsConstructor
public
class
AuthController
{
public
class
AuthController
{
final
I18n
i18n
;
final
Auths
auths
;
final
Auths
auths
;
final
UserRepository
userRepository
;
final
UserRepository
userRepository
;
final
LoginLogRepository
loginLogRepository
;
@RateLimiter
(
time
=
1
,
count
=
1
)
@RateLimiter
(
time
=
1
,
count
=
1
)
@Operation
(
summary
=
"注册"
)
@Operation
(
summary
=
"注册"
)
...
@@ -93,39 +101,89 @@ public class AuthController {
...
@@ -93,39 +101,89 @@ public class AuthController {
@Operation
(
summary
=
"登录"
)
@Operation
(
summary
=
"登录"
)
@PostMapping
(
"login"
)
@PostMapping
(
"login"
)
public
Result
<
LoginVo
>
login
(
@ParameterObject
@Validated
LoginParam
param
,
HttpServletRequest
request
)
{
public
Result
<
LoginVo
>
login
(
@ParameterObject
@Validated
LoginParam
param
,
HttpServletRequest
request
)
{
// 查询用户信息是否匹配
// 获取登录 IP
User
user
=
userRepository
.
findByAccount
(
param
.
getAccount
());
// String ip = "222.244.92.58";
if
(
user
==
null
)
{
String
ip
=
IpUtil
.
getClientIp
(
request
);
throw
BusinessException
.
i18n
(
"Code.100003"
);
// 获取登录 User-Agent
}
String
ua
=
request
.
getHeader
(
"User-Agent"
);
// 构建登录日志
LoginLog
loginLog
=
LoginLog
.
builder
()
.
account
(
param
.
getAccount
())
.
ip
(
ip
)
.
location
(
IpUtil
.
getIpRegion
(
ip
))
.
ua
(
ua
)
.
build
();
// 检查用户是否已被删除
// 尝试解析 User-Agent
if
(
Boolean
.
TRUE
.
equals
(
user
.
getDeleted
()))
{
UserAgent
userAgent
=
UserAgentUtil
.
parse
(
ua
);
throw
BusinessException
.
i18n
(
"Code.100004"
);
if
(
Objects
.
nonNull
(
userAgent
))
{
}
// 获取操作系统
OS
os
=
userAgent
.
getOs
();
if
(
Objects
.
nonNull
(
os
))
{
loginLog
.
setOs
(
os
.
toString
());
}
// 检查用户是否被允许登录
// 获取浏览器
if
(
Boolean
.
TRUE
.
equals
(
user
.
getDisabled
()))
{
Browser
browser
=
userAgent
.
getBrowser
();
throw
BusinessException
.
i18n
(
"Code.100005"
);
if
(
Objects
.
nonNull
(
browser
))
{
}
loginLog
.
setBrowser
(
browser
.
toString
());
}
// 检查密码
// 获取平台
String
cps
=
SaSecureUtil
.
sha256
(
param
.
getPassword
());
Platform
platform
=
userAgent
.
getPlatform
();
if
(!
cps
.
equals
(
user
.
getPassword
()))
{
if
(
Objects
.
nonNull
(
platform
))
{
throw
BusinessException
.
i18n
(
"Code.100003"
);
loginLog
.
setPlatform
(
platform
.
toString
());
}
}
}
// 更新用户信息
try
{
user
.
setLastLoginIp
(
Commons
.
getClientIpAddress
(
request
));
// 查询用户信息是否匹配
user
.
setLastLoginTime
(
LocalDateTime
.
now
());
User
user
=
userRepository
.
findByAccount
(
param
.
getAccount
());
userRepository
.
saveAndFlush
(
user
);
if
(
user
==
null
)
{
throw
BusinessException
.
i18n
(
"Code.100003"
);
}
// 检查用户是否已被删除
if
(
Boolean
.
TRUE
.
equals
(
user
.
getDeleted
()))
{
throw
BusinessException
.
i18n
(
"Code.100004"
);
}
// 登录
// 检查用户是否被允许登录
StpUtil
.
login
(
user
.
getId
());
if
(
Boolean
.
TRUE
.
equals
(
user
.
getDisabled
()))
{
throw
BusinessException
.
i18n
(
"Code.100005"
);
}
// 检查密码
String
cps
=
SaSecureUtil
.
sha256
(
param
.
getPassword
());
if
(!
cps
.
equals
(
user
.
getPassword
()))
{
throw
BusinessException
.
i18n
(
"Code.100003"
);
}
// 构建用户所需信息
// 更新用户信息
LoginVo
vo
=
LoginVo
.
builder
().
userId
(
user
.
getId
()).
token
(
StpUtil
.
getTokenValue
()).
build
();
user
.
setLastLoginIp
(
IpUtil
.
getClientIp
(
request
));
return
Result
.
ok
(
vo
);
user
.
setLastLoginTime
(
LocalDateTime
.
now
());
userRepository
.
saveAndFlush
(
user
);
// 登录
StpUtil
.
login
(
user
.
getId
());
// 登录日志状态
loginLog
.
setStatus
(
true
);
loginLog
.
setMsg
(
i18n
.
get
(
Status
.
OK
.
getReasonPhrase
()));
// 构建用户所需信息
LoginVo
vo
=
LoginVo
.
builder
().
userId
(
user
.
getId
()).
token
(
StpUtil
.
getTokenValue
()).
build
();
return
Result
.
ok
(
vo
);
}
catch
(
Exception
e
)
{
// 登录日志状态
loginLog
.
setStatus
(
false
);
loginLog
.
setMsg
(
e
.
getMessage
());
throw
e
;
}
finally
{
// 保存登录日志
loginLogRepository
.
saveAndFlush
(
loginLog
);
}
}
}
@Operation
(
summary
=
"检查登录"
)
@Operation
(
summary
=
"检查登录"
)
...
...
basic-common/core/build.gradle
浏览文件 @
1704ab90
...
@@ -31,4 +31,5 @@ dependencies {
...
@@ -31,4 +31,5 @@ dependencies {
// https://mvnrepository.com/artifact/org.jetbrains/annotations
// https://mvnrepository.com/artifact/org.jetbrains/annotations
implementation
"org.jetbrains:annotations:${jetbrainsAnnotationsVersion}"
implementation
"org.jetbrains:annotations:${jetbrainsAnnotationsVersion}"
}
}
basic-common/core/src/main/java/com/yiring/common/aspect/RateLimiterAspect.java
浏览文件 @
1704ab90
...
@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
...
@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.core.Redis
;
import
com.yiring.common.core.Redis
;
import
com.yiring.common.core.Status
;
import
com.yiring.common.core.Status
;
import
com.yiring.common.util.
Commons
;
import
com.yiring.common.util.
IpUtil
;
import
com.yiring.common.utils.Contexts
;
import
com.yiring.common.utils.Contexts
;
import
jakarta.servlet.http.Cookie
;
import
jakarta.servlet.http.Cookie
;
import
jakarta.servlet.http.HttpServletRequest
;
import
jakarta.servlet.http.HttpServletRequest
;
...
@@ -81,7 +81,7 @@ public class RateLimiterAspect {
...
@@ -81,7 +81,7 @@ public class RateLimiterAspect {
StringBuilder
sb
=
new
StringBuilder
(
prefixKey
);
StringBuilder
sb
=
new
StringBuilder
(
prefixKey
);
HttpServletRequest
request
=
Contexts
.
getRequest
();
HttpServletRequest
request
=
Contexts
.
getRequest
();
// 获取请求的 IP 地址
// 获取请求的 IP 地址
sb
.
append
(
Commons
.
getClientIpAddress
(
request
));
sb
.
append
(
IpUtil
.
getClientIp
(
request
));
// 考虑登录用户的 token
// 考虑登录用户的 token
if
(
StrUtil
.
isNotBlank
(
tokenName
))
{
if
(
StrUtil
.
isNotBlank
(
tokenName
))
{
...
...
basic-common/core/src/main/java/com/yiring/common/aspect/RequestAspect.java
浏览文件 @
1704ab90
...
@@ -6,7 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
...
@@ -6,7 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
import
com.alibaba.fastjson2.JSONWriter
;
import
com.alibaba.fastjson2.JSONWriter
;
import
com.yiring.common.constant.DateFormatter
;
import
com.yiring.common.constant.DateFormatter
;
import
com.yiring.common.core.Result
;
import
com.yiring.common.core.Result
;
import
com.yiring.common.util.
Commons
;
import
com.yiring.common.util.
IpUtil
;
import
com.yiring.common.utils.Contexts
;
import
com.yiring.common.utils.Contexts
;
import
jakarta.servlet.http.HttpServletRequest
;
import
jakarta.servlet.http.HttpServletRequest
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
...
@@ -97,7 +97,7 @@ public class RequestAspect {
...
@@ -97,7 +97,7 @@ public class RequestAspect {
// 打印请求日志 (Optional Replace: MDC, Trace)
// 打印请求日志 (Optional Replace: MDC, Trace)
log
.
info
(
log
.
info
(
"[Request] IP: {}, Method: {}, URL: {}, Status: {}, Times: {}{}"
,
"[Request] IP: {}, Method: {}, URL: {}, Status: {}, Times: {}{}"
,
Commons
.
getClientIpAddress
(
request
),
IpUtil
.
getClientIp
(
request
),
request
.
getMethod
(),
request
.
getMethod
(),
request
.
getRequestURL
(),
request
.
getRequestURL
(),
status
,
status
,
...
...
basic-common/util/build.gradle
浏览文件 @
1704ab90
...
@@ -13,4 +13,7 @@ dependencies {
...
@@ -13,4 +13,7 @@ dependencies {
// hutool
// hutool
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-extra:${hutoolVersion}"
implementation
"cn.hutool:hutool-extra:${hutoolVersion}"
// ip2region
implementation
"org.lionsoul:ip2region:${ip2regionVersion}"
}
}
basic-common/util/src/main/java/com/yiring/common/jackson/ObjectMappingSerializer.java
浏览文件 @
1704ab90
...
@@ -41,7 +41,7 @@ public class ObjectMappingSerializer extends StdSerializer<Object> implements Co
...
@@ -41,7 +41,7 @@ public class ObjectMappingSerializer extends StdSerializer<Object> implements Co
String
mapping
=
mappingSerialize
.
mapping
();
String
mapping
=
mappingSerialize
.
mapping
();
Map
<
String
,
String
>
map
=
new
HashMap
<>();
Map
<
String
,
String
>
map
=
new
HashMap
<>();
if
(
mapping
.
length
()
>
0
)
{
if
(
!
mapping
.
isEmpty
()
)
{
String
[]
strings
=
mapping
.
split
(
","
);
String
[]
strings
=
mapping
.
split
(
","
);
for
(
String
str
:
strings
)
{
for
(
String
str
:
strings
)
{
String
[]
split
=
str
.
split
(
":"
);
String
[]
split
=
str
.
split
(
":"
);
...
@@ -57,7 +57,7 @@ public class ObjectMappingSerializer extends StdSerializer<Object> implements Co
...
@@ -57,7 +57,7 @@ public class ObjectMappingSerializer extends StdSerializer<Object> implements Co
@Override
@Override
public
void
serialize
(
Object
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
public
void
serialize
(
Object
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
throws
IOException
{
String
text
=
mapping
.
get
(
Objects
.
toString
(
value
));
String
text
=
mapping
.
get
(
Objects
.
toString
(
value
));
if
(
text
==
null
||
text
.
length
()
==
0
)
{
if
(
text
==
null
||
text
.
isEmpty
()
)
{
gen
.
writeObject
(
value
);
gen
.
writeObject
(
value
);
}
else
{
}
else
{
gen
.
writeString
(
text
);
gen
.
writeString
(
text
);
...
...
basic-common/util/src/main/java/com/yiring/common/util/Commons.java
浏览文件 @
1704ab90
...
@@ -2,7 +2,6 @@
...
@@ -2,7 +2,6 @@
package
com
.
yiring
.
common
.
util
;
package
com
.
yiring
.
common
.
util
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.collection.CollUtil
;
import
jakarta.servlet.http.HttpServletRequest
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.util.*
;
import
java.util.*
;
import
lombok.experimental.UtilityClass
;
import
lombok.experimental.UtilityClass
;
...
@@ -22,41 +21,6 @@ import org.springframework.beans.BeanUtils;
...
@@ -22,41 +21,6 @@ import org.springframework.beans.BeanUtils;
public
class
Commons
{
public
class
Commons
{
/**
/**
* 代理 IP 请求头
*/
private
static
final
String
[]
HEADERS_TO_TRY
=
{
"X-Forwarded-For"
,
"Proxy-Client-IP"
,
"WL-Proxy-Client-IP"
,
"HTTP_X_FORWARDED_FOR"
,
"HTTP_X_FORWARDED"
,
"HTTP_X_CLUSTER_CLIENT_IP"
,
"HTTP_CLIENT_IP"
,
"HTTP_FORWARDED_FOR"
,
"HTTP_FORWARDED"
,
"HTTP_VIA"
,
"REMOTE_ADDR"
,
"X-Real-IP"
,
};
/***
* 获取客户端ip地址(可以穿透代理)
*
* @param request HttpServletRequest
* @return IP
*/
public
String
getClientIpAddress
(
HttpServletRequest
request
)
{
for
(
String
header
:
HEADERS_TO_TRY
)
{
String
ip
=
request
.
getHeader
(
header
);
if
(
ip
!=
null
&&
!
ip
.
isEmpty
()
&&
!
"unknown"
.
equalsIgnoreCase
(
ip
))
{
return
ip
;
}
}
return
request
.
getRemoteAddr
();
}
/**
* 随机生成一个UUID
* 随机生成一个UUID
*
*
* @return UUID 字符串
* @return UUID 字符串
...
...
basic-common/util/src/main/java/com/yiring/common/util/IpUtil.java
0 → 100644
浏览文件 @
1704ab90
/* (C) 2024 YiRing, Inc. */
package
com
.
yiring
.
common
.
util
;
import
jakarta.servlet.http.HttpServletRequest
;
import
java.io.InputStream
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
lombok.experimental.UtilityClass
;
import
lombok.extern.slf4j.Slf4j
;
import
org.lionsoul.ip2region.xdb.Searcher
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.util.FileCopyUtils
;
/**
* @author Jim
*/
@SuppressWarnings
(
"unused"
)
@Slf4j
@UtilityClass
public
class
IpUtil
{
/**
* 代理 IP 请求头
*/
private
static
final
String
[]
HEADERS_TO_TRY
=
{
"X-Forwarded-For"
,
"Proxy-Client-IP"
,
"WL-Proxy-Client-IP"
,
"HTTP_X_FORWARDED_FOR"
,
"HTTP_X_FORWARDED"
,
"HTTP_X_CLUSTER_CLIENT_IP"
,
"HTTP_CLIENT_IP"
,
"HTTP_FORWARDED_FOR"
,
"HTTP_FORWARDED"
,
"HTTP_VIA"
,
"REMOTE_ADDR"
,
"X-Real-IP"
,
};
private
static
Searcher
searcher
;
static
{
try
{
ClassPathResource
resource
=
new
ClassPathResource
(
"ipdb/ip2region.xdb"
);
InputStream
inputStream
=
resource
.
getInputStream
();
byte
[]
bytes
=
FileCopyUtils
.
copyToByteArray
(
inputStream
);
searcher
=
Searcher
.
newWithBuffer
(
bytes
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
}
/***
* 获取客户端ip地址(可以穿透代理)
*
* @param request HttpServletRequest
* @return IP
*/
public
String
getClientIp
(
HttpServletRequest
request
)
{
for
(
String
header
:
HEADERS_TO_TRY
)
{
String
ip
=
request
.
getHeader
(
header
);
if
(
ip
!=
null
&&
!
ip
.
isEmpty
()
&&
!
"unknown"
.
equalsIgnoreCase
(
ip
))
{
return
ip
;
}
}
return
request
.
getRemoteAddr
();
}
/**
* 判断是否为合法 IP
*/
public
static
boolean
checkIp
(
String
ipAddress
)
{
String
ip
=
"([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"
;
Pattern
pattern
=
Pattern
.
compile
(
ip
);
Matcher
matcher
=
pattern
.
matcher
(
ipAddress
);
return
matcher
.
matches
();
}
/**
* 获取 ip 属地
*
* @param ip ip
* @return ip 属地
*/
public
static
String
getIpRegion
(
String
ip
)
{
if
(
checkIp
(
ip
))
{
try
{
// searchIpInfo 的数据格式: 国家|区域|省份|城市|ISP
String
searchIpInfo
=
searcher
.
search
(
ip
);
String
[]
splitIpInfo
=
searchIpInfo
.
split
(
"\\|"
);
if
(
splitIpInfo
.
length
>
0
)
{
if
(
"中国"
.
equals
(
splitIpInfo
[
0
]))
{
// 国内属地返回城市
return
splitIpInfo
[
3
];
}
else
if
(
"0"
.
equals
(
splitIpInfo
[
0
]))
{
if
(
"内网IP"
.
equals
(
splitIpInfo
[
4
]))
{
// 内网 IP
return
splitIpInfo
[
4
];
}
}
else
{
// 国外属地返回国家
return
splitIpInfo
[
0
];
}
}
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
}
return
""
;
}
else
{
throw
new
IllegalArgumentException
(
"Illegal IP address"
);
}
}
}
basic-common/util/src/main/resources/ipdb/README.md
0 → 100644
浏览文件 @
1704ab90
# ip2region
-
[
代码库
](
https://github.com/lionsoul2014/ip2region
)
-
[
ip2region.xdb
](
https://github.com/lionsoul2014/ip2region/blob/master/data/ip2region.xdb
)
basic-common/util/src/main/resources/ipdb/ip2region.xdb
0 → 100644
浏览文件 @
1704ab90
File added
build.gradle
浏览文件 @
1704ab90
...
@@ -64,6 +64,8 @@ ext {
...
@@ -64,6 +64,8 @@ ext {
jetbrainsAnnotationsVersion
=
'24.1.0'
jetbrainsAnnotationsVersion
=
'24.1.0'
// https://central.sonatype.com/artifact/org.apache.pdfbox/pdfbox
// https://central.sonatype.com/artifact/org.apache.pdfbox/pdfbox
pdfboxVersion
=
'3.0.2'
pdfboxVersion
=
'3.0.2'
// https://central.sonatype.com/artifact/org.lionsoul/ip2region
ip2regionVersion
=
'2.7.0'
// https://central.sonatype.com/artifact/net.bramp.ffmpeg/ffmpeg
// https://central.sonatype.com/artifact/net.bramp.ffmpeg/ffmpeg
// FIXED: ffmpeg 4.x
// FIXED: ffmpeg 4.x
ffmpegWrapperVersion
=
'0.8.0'
ffmpegWrapperVersion
=
'0.8.0'
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论