mirror of
https://github.com/yangzongzhuan/RuoYi.git
synced 2025-12-18 16:35:53 +00:00
使用yauaa代替bitwalker
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -21,7 +21,7 @@
|
|||||||
<mybatis-spring-boot.version>3.0.4</mybatis-spring-boot.version>
|
<mybatis-spring-boot.version>3.0.4</mybatis-spring-boot.version>
|
||||||
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
|
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
|
||||||
<druid.version>1.2.27</druid.version>
|
<druid.version>1.2.27</druid.version>
|
||||||
<bitwalker.version>1.21</bitwalker.version>
|
<yauaa.version>7.32.0</yauaa.version>
|
||||||
<kaptcha.version>2.3.3</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<pagehelper.boot.version>2.1.1</pagehelper.boot.version>
|
<pagehelper.boot.version>2.1.1</pagehelper.boot.version>
|
||||||
<fastjson.version>1.2.83</fastjson.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
@@ -124,9 +124,9 @@
|
|||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>eu.bitwalker</groupId>
|
<groupId>nl.basjes.parse.useragent</groupId>
|
||||||
<artifactId>UserAgentUtils</artifactId>
|
<artifactId>yauaa</artifactId>
|
||||||
<version>${bitwalker.version}</version>
|
<version>${yauaa.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- pagehelper 分页插件 -->
|
<!-- pagehelper 分页插件 -->
|
||||||
|
|||||||
@@ -84,10 +84,10 @@
|
|||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- yml解析器 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.yaml</groupId>
|
<groupId>nl.basjes.parse.useragent</groupId>
|
||||||
<artifactId>snakeyaml</artifactId>
|
<artifactId>yauaa</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- servlet包 -->
|
<!-- servlet包 -->
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
package com.ruoyi.common.utils.http;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import nl.basjes.parse.useragent.UserAgent;
|
||||||
|
import nl.basjes.parse.useragent.UserAgentAnalyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UserAgent解析工具类
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class UserAgentUtils
|
||||||
|
{
|
||||||
|
public static final String UNKNOWN = "";
|
||||||
|
|
||||||
|
// 浏览器正则表达式模式
|
||||||
|
private static final Pattern CHROME_PATTERN = Pattern.compile("Chrome/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern FIREFOX_PATTERN = Pattern.compile("Firefox/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern EDGE_PATTERN = Pattern.compile("Edg(?:e)?/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern SAFARI_PATTERN = Pattern.compile("Version/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern OPERA_PATTERN = Pattern.compile("Opera/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern IE_PATTERN = Pattern.compile("(?:MSIE |Trident/.*rv:)(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern SAMSUNG_PATTERN = Pattern.compile("SamsungBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern UC_PATTERN = Pattern.compile("UCBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern QQ_PATTERN = Pattern.compile("QQBrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern WECHAT_PATTERN = Pattern.compile("MicroMessenger/(\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern BAIDU_PATTERN = Pattern.compile("baidubrowser/(\\d+)(?:\\.\\d+)*");
|
||||||
|
|
||||||
|
// 操作系统正则表达式模式
|
||||||
|
private static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows NT (\\d+\\.\\d+)");
|
||||||
|
private static final Pattern MACOS_PATTERN = Pattern.compile("Mac OS X (\\d+[_\\d]*)");
|
||||||
|
private static final Pattern ANDROID_PATTERN = Pattern.compile("Android (\\d+)(?:\\.\\d+)*");
|
||||||
|
private static final Pattern IOS_PATTERN = Pattern.compile("OS[\\s_](\\d+)(?:_\\d+)*");
|
||||||
|
private static final Pattern LINUX_PATTERN = Pattern.compile("Linux");
|
||||||
|
private static final Pattern CHROMEOS_PATTERN = Pattern.compile("CrOS");
|
||||||
|
|
||||||
|
private static final UserAgentAnalyzer userAgentAnalyzer = UserAgentAnalyzer
|
||||||
|
.newBuilder().hideMatcherLoadStats()
|
||||||
|
.withCache(5000)
|
||||||
|
.showMinimalVersion()
|
||||||
|
.withField(UserAgent.AGENT_NAME_VERSION)
|
||||||
|
.withField(UserAgent.OPERATING_SYSTEM_NAME_VERSION)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端浏览器
|
||||||
|
*/
|
||||||
|
public static String getBrowser(String userAgent)
|
||||||
|
{
|
||||||
|
UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
|
||||||
|
String agentNameVersion = iua.get(UserAgent.AGENT_NAME_VERSION).getValue();
|
||||||
|
if (StringUtils.isBlank(agentNameVersion) || agentNameVersion.contains("??"))
|
||||||
|
{
|
||||||
|
return formatBrowser(userAgent);
|
||||||
|
}
|
||||||
|
return agentNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端操作系统
|
||||||
|
*/
|
||||||
|
public static String getOperatingSystem(String userAgent)
|
||||||
|
{
|
||||||
|
UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
|
||||||
|
String operatingSystemNameVersion = iua.get(UserAgent.OPERATING_SYSTEM_NAME_VERSION).getValue();
|
||||||
|
if (StringUtils.isBlank(operatingSystemNameVersion) || operatingSystemNameVersion.contains("??"))
|
||||||
|
{
|
||||||
|
return formatOperatingSystem(userAgent);
|
||||||
|
}
|
||||||
|
return operatingSystemNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全面浏览器检测
|
||||||
|
*/
|
||||||
|
private static String formatBrowser(String browser)
|
||||||
|
{
|
||||||
|
// Chrome系列浏览器
|
||||||
|
Matcher chromeMatcher = CHROME_PATTERN.matcher(browser);
|
||||||
|
if (chromeMatcher.find() && (browser.contains("Chrome") || browser.contains("CriOS")))
|
||||||
|
{
|
||||||
|
return "Chrome" + chromeMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Firefox
|
||||||
|
Matcher firefoxMatcher = FIREFOX_PATTERN.matcher(browser);
|
||||||
|
if (firefoxMatcher.find())
|
||||||
|
{
|
||||||
|
return "Firefox" + firefoxMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Edge浏览器
|
||||||
|
Matcher edgeMatcher = EDGE_PATTERN.matcher(browser);
|
||||||
|
if (edgeMatcher.find())
|
||||||
|
{
|
||||||
|
return "Edge" + edgeMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Safari浏览器(需排除Chrome)
|
||||||
|
Matcher safariMatcher = SAFARI_PATTERN.matcher(browser);
|
||||||
|
if (safariMatcher.find() && !browser.contains("Chrome"))
|
||||||
|
{
|
||||||
|
return "Safari" + safariMatcher.group(1);
|
||||||
|
}
|
||||||
|
// 微信内置浏览器
|
||||||
|
Matcher wechatMatcher = WECHAT_PATTERN.matcher(browser);
|
||||||
|
if (wechatMatcher.find())
|
||||||
|
{
|
||||||
|
return "WeChat" + wechatMatcher.group(1);
|
||||||
|
}
|
||||||
|
// UC浏览器
|
||||||
|
Matcher ucMatcher = UC_PATTERN.matcher(browser);
|
||||||
|
if (ucMatcher.find())
|
||||||
|
{
|
||||||
|
return "UC Browser" + ucMatcher.group(1);
|
||||||
|
}
|
||||||
|
// QQ浏览器
|
||||||
|
Matcher qqMatcher = QQ_PATTERN.matcher(browser);
|
||||||
|
if (qqMatcher.find())
|
||||||
|
{
|
||||||
|
return "QQ Browser" + qqMatcher.group(1);
|
||||||
|
}
|
||||||
|
// 百度浏览器
|
||||||
|
Matcher baiduMatcher = BAIDU_PATTERN.matcher(browser);
|
||||||
|
if (baiduMatcher.find())
|
||||||
|
{
|
||||||
|
return "Baidu Browser" + baiduMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Samsung浏览器
|
||||||
|
Matcher samsungMatcher = SAMSUNG_PATTERN.matcher(browser);
|
||||||
|
if (samsungMatcher.find())
|
||||||
|
{
|
||||||
|
return "Samsung Browser" + samsungMatcher.group(1);
|
||||||
|
}
|
||||||
|
// Opera浏览器
|
||||||
|
Matcher operaMatcher = OPERA_PATTERN.matcher(browser);
|
||||||
|
if (operaMatcher.find())
|
||||||
|
{
|
||||||
|
return "Opera" + operaMatcher.group(1);
|
||||||
|
}
|
||||||
|
// IE浏览器
|
||||||
|
Matcher ieMatcher = IE_PATTERN.matcher(browser);
|
||||||
|
if (ieMatcher.find())
|
||||||
|
{
|
||||||
|
return "Internet Explorer" + ieMatcher.group(1);
|
||||||
|
}
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测操作系统
|
||||||
|
*/
|
||||||
|
private static String formatOperatingSystem(String operatingSystem)
|
||||||
|
{
|
||||||
|
// Windows系统
|
||||||
|
Matcher windowsMatcher = WINDOWS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (windowsMatcher.find())
|
||||||
|
{
|
||||||
|
return "Windows" + getWindowsVersionDisplay(windowsMatcher.group(1));
|
||||||
|
}
|
||||||
|
// macOS系统
|
||||||
|
Matcher macMatcher = MACOS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (macMatcher.find())
|
||||||
|
{
|
||||||
|
String version = macMatcher.group(1).replace("_", ".");
|
||||||
|
return "macOS" + extractMajorVersion(version);
|
||||||
|
}
|
||||||
|
// Android系统
|
||||||
|
Matcher androidMatcher = ANDROID_PATTERN.matcher(operatingSystem);
|
||||||
|
if (androidMatcher.find())
|
||||||
|
{
|
||||||
|
return "Android" + extractMajorVersion(androidMatcher.group(1));
|
||||||
|
}
|
||||||
|
// iOS系统
|
||||||
|
Matcher iosMatcher = IOS_PATTERN.matcher(operatingSystem);
|
||||||
|
if (iosMatcher.find() && (operatingSystem.contains("iPhone") || operatingSystem.contains("iPad")))
|
||||||
|
{
|
||||||
|
return "iOS" + extractMajorVersion(iosMatcher.group(1));
|
||||||
|
}
|
||||||
|
// Linux系统
|
||||||
|
if (LINUX_PATTERN.matcher(operatingSystem).find() && !operatingSystem.contains("Android"))
|
||||||
|
{
|
||||||
|
return "Linux";
|
||||||
|
}
|
||||||
|
// Chrome OS
|
||||||
|
if (CHROMEOS_PATTERN.matcher(operatingSystem).find())
|
||||||
|
{
|
||||||
|
return "Chrome OS";
|
||||||
|
}
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取优化的主版本号
|
||||||
|
*/
|
||||||
|
private static String extractMajorVersion(String fullVersion)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(fullVersion))
|
||||||
|
{
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 清理版本号中的非数字字符
|
||||||
|
String cleanVersion = fullVersion.replaceAll("[^0-9.]", "");
|
||||||
|
String[] parts = cleanVersion.split("\\.");
|
||||||
|
if (parts.length > 0)
|
||||||
|
{
|
||||||
|
String firstPart = parts[0];
|
||||||
|
if (firstPart.matches("\\d+"))
|
||||||
|
{
|
||||||
|
int version = Integer.parseInt(firstPart);
|
||||||
|
|
||||||
|
// 处理三位数版本号(如142 -> 14)
|
||||||
|
if (version >= 100)
|
||||||
|
{
|
||||||
|
return String.valueOf(version / 10);
|
||||||
|
}
|
||||||
|
return firstPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e)
|
||||||
|
{
|
||||||
|
// 版本号解析失败,返回原始值
|
||||||
|
}
|
||||||
|
return fullVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows版本号显示优化
|
||||||
|
*/
|
||||||
|
private static String getWindowsVersionDisplay(String version)
|
||||||
|
{
|
||||||
|
switch (version)
|
||||||
|
{
|
||||||
|
case "10.0":
|
||||||
|
return "10";
|
||||||
|
case "6.3":
|
||||||
|
return "8.1";
|
||||||
|
case "6.2":
|
||||||
|
return "8";
|
||||||
|
case "6.1":
|
||||||
|
return "7";
|
||||||
|
case "6.0":
|
||||||
|
return "Vista";
|
||||||
|
case "5.1":
|
||||||
|
return "XP";
|
||||||
|
case "5.0":
|
||||||
|
return "2000";
|
||||||
|
default:
|
||||||
|
return extractMajorVersion(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,12 +73,6 @@
|
|||||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>eu.bitwalker</groupId>
|
|
||||||
<artifactId>UserAgentUtils</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 获取系统信息 -->
|
<!-- 获取系统信息 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.oshi</groupId>
|
<groupId>com.github.oshi</groupId>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.ruoyi.common.utils.LogUtils;
|
|||||||
import com.ruoyi.common.utils.ServletUtils;
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
import com.ruoyi.common.utils.ShiroUtils;
|
import com.ruoyi.common.utils.ShiroUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.http.UserAgentUtils;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import com.ruoyi.framework.shiro.session.OnlineSession;
|
import com.ruoyi.framework.shiro.session.OnlineSession;
|
||||||
import com.ruoyi.system.domain.SysLogininfor;
|
import com.ruoyi.system.domain.SysLogininfor;
|
||||||
@@ -17,7 +18,6 @@ import com.ruoyi.system.domain.SysUserOnline;
|
|||||||
import com.ruoyi.system.service.ISysOperLogService;
|
import com.ruoyi.system.service.ISysOperLogService;
|
||||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||||
import com.ruoyi.system.service.impl.SysLogininforServiceImpl;
|
import com.ruoyi.system.service.impl.SysLogininforServiceImpl;
|
||||||
import eu.bitwalker.useragentutils.UserAgent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步工厂(产生任务用)
|
* 异步工厂(产生任务用)
|
||||||
@@ -91,7 +91,7 @@ public class AsyncFactory
|
|||||||
*/
|
*/
|
||||||
public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args)
|
public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args)
|
||||||
{
|
{
|
||||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
final String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||||
final String ip = ShiroUtils.getIp();
|
final String ip = ShiroUtils.getIp();
|
||||||
return new TimerTask()
|
return new TimerTask()
|
||||||
{
|
{
|
||||||
@@ -108,9 +108,9 @@ public class AsyncFactory
|
|||||||
// 打印信息到日志
|
// 打印信息到日志
|
||||||
sys_user_logger.info(s.toString(), args);
|
sys_user_logger.info(s.toString(), args);
|
||||||
// 获取客户端操作系统
|
// 获取客户端操作系统
|
||||||
String os = userAgent.getOperatingSystem().getName();
|
String os = UserAgentUtils.getOperatingSystem(userAgent);
|
||||||
// 获取客户端浏览器
|
// 获取客户端浏览器
|
||||||
String browser = userAgent.getBrowser().getName();
|
String browser = UserAgentUtils.getBrowser(userAgent);
|
||||||
// 封装对象
|
// 封装对象
|
||||||
SysLogininfor logininfor = new SysLogininfor();
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
logininfor.setLoginName(username);
|
logininfor.setLoginName(username);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package com.ruoyi.framework.shiro.session;
|
package com.ruoyi.framework.shiro.session;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import org.apache.shiro.session.Session;
|
import org.apache.shiro.session.Session;
|
||||||
import org.apache.shiro.session.mgt.SessionContext;
|
import org.apache.shiro.session.mgt.SessionContext;
|
||||||
import org.apache.shiro.session.mgt.SessionFactory;
|
import org.apache.shiro.session.mgt.SessionFactory;
|
||||||
import org.apache.shiro.web.session.mgt.WebSessionContext;
|
import org.apache.shiro.web.session.mgt.WebSessionContext;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import com.ruoyi.common.utils.IpUtils;
|
import com.ruoyi.common.utils.IpUtils;
|
||||||
import eu.bitwalker.useragentutils.UserAgent;
|
import com.ruoyi.common.utils.http.UserAgentUtils;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义sessionFactory会话
|
* 自定义sessionFactory会话
|
||||||
@@ -27,11 +27,11 @@ public class OnlineSessionFactory implements SessionFactory
|
|||||||
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
|
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
|
||||||
if (request != null)
|
if (request != null)
|
||||||
{
|
{
|
||||||
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
|
String userAgent = request.getHeader("User-Agent");
|
||||||
// 获取客户端操作系统
|
// 获取客户端操作系统
|
||||||
String os = userAgent.getOperatingSystem().getName();
|
String os = UserAgentUtils.getOperatingSystem(userAgent);
|
||||||
// 获取客户端浏览器
|
// 获取客户端浏览器
|
||||||
String browser = userAgent.getBrowser().getName();
|
String browser = UserAgentUtils.getBrowser(userAgent);
|
||||||
session.setHost(IpUtils.getIpAddr(request));
|
session.setHost(IpUtils.getIpAddr(request));
|
||||||
session.setBrowser(browser);
|
session.setBrowser(browser);
|
||||||
session.setOs(os);
|
session.setOs(os);
|
||||||
|
|||||||
Reference in New Issue
Block a user