java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot获取浏览器信息

SpringBoot获取浏览器信息的多种实现方式

作者:匆匆忙忙游刃有余

在Web开发中,获取用户浏览器信息是常见需求,可用于统计分析、个性化展示、安全防护等场景,SpringBoot提供了多种方式来获取这些信息,下面是详细实现方法,需要的朋友可以参考下

引言

在Web开发中,获取用户浏览器信息是常见需求,可用于统计分析、个性化展示、安全防护等场景。SpringBoot提供了多种方式来获取这些信息,下面是详细实现方法。

一、获取基本请求信息

1. 获取客户端IP地址

在SpringBoot中,最基本的方法是通过HttpServletRequest对象获取IP地址,但需要注意反向代理的情况。

public class IpUtils {
    private static final String UNKNOWN = "unknown";
    
    /**
     * 获取真实IP地址(考虑反向代理情况)
     */
    public static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return UNKNOWN;
        }
        
        // 尝试从各种代理头中获取IP
        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("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        
        // 如果还是没有获取到,使用RemoteAddr
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        
        // 处理多级代理的情况,取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        
        // 本地测试情况
        if ("0:0:0:0:0:0:0:1".equals(ip)) {
            ip = "127.0.0.1";
        }
        
        return ip;
    }
}

2. 获取请求头信息

@RestController
public class BrowserInfoController {
    
    @GetMapping("/browser-info")
    public Map<String, String> getBrowserInfo(HttpServletRequest request) {
        Map<String, String> info = new HashMap<>();
        
        // 获取IP地址
        info.put("ip", IpUtils.getIpAddr(request));
        
        // 获取User-Agent
        info.put("userAgent", request.getHeader("User-Agent"));
        
        // 获取其他请求头信息
        info.put("accept", request.getHeader("Accept"));
        info.put("acceptLanguage", request.getHeader("Accept-Language"));
        info.put("referer", request.getHeader("Referer"));
        info.put("contentType", request.getHeader("Content-Type"));
        info.put("encoding", request.getHeader("Accept-Encoding"));
        info.put("connection", request.getHeader("Connection"));
        
        return info;
    }
}

二、使用UserAgentUtils解析浏览器信息

1. 添加依赖

<!-- pom.xml -->
<dependency>
    <groupId>eu.bitwalker</groupId>
    <artifactId>UserAgentUtils</artifactId>
    <version>1.21</version>
</dependency>

2. 解析浏览器详细信息

public class BrowserUtils {
    
    /**
     * 解析浏览器信息
     */
    public static Map<String, Object> parseBrowserInfo(String userAgentString) {
        Map<String, Object> result = new HashMap<>();
        
        // 创建UserAgent对象
        UserAgent userAgent = UserAgent.parseUserAgentString(userAgentString);
        
        // 获取浏览器信息
        Browser browser = userAgent.getBrowser();
        Version browserVersion = userAgent.getBrowserVersion();
        result.put("browser", browser.getName());
        result.put("browserVersion", browserVersion.getVersion());
        
        // 获取操作系统信息
        OperatingSystem os = userAgent.getOperatingSystem();
        result.put("operatingSystem", os.getName());
        
        // 获取设备信息
        DeviceType deviceType = os.getDeviceType();
        result.put("deviceType", deviceType.getName());
        
        // 判断是否是移动设备
        result.put("isMobile", os.isMobileDevice());
        
        // 获取渲染引擎
        RenderingEngine engine = userAgent.getRenderingEngine();
        result.put("renderingEngine", engine.name());
        
        return result;
    }
}

3. 在Controller中使用

@RestController
public class BrowserInfoController {
    
    @GetMapping("/detailed-browser-info")
    public Map<String, Object> getDetailedBrowserInfo(HttpServletRequest request) {
        Map<String, Object> info = new HashMap<>();
        
        // 获取IP
        String ip = IpUtils.getIpAddr(request);
        info.put("ip", ip);
        
        // 获取并解析User-Agent
        String userAgentString = request.getHeader("User-Agent");
        Map<String, Object> browserDetails = BrowserUtils.parseBrowserInfo(userAgentString);
        info.putAll(browserDetails);
        
        return info;
    }
}

三、获取IP地址归属地

1. 使用ip2region库(本地解析)

添加依赖:

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.6.3</version>
</dependency>

实现代码:

public class IpRegionUtils {
    private static Searcher searcher;
    
    // 初始化ip2region
    static {
        try {
            // 下载xdb文件到resources目录
            String dbPath = IpRegionUtils.class.getResource("/ip2region.xdb").getPath();
            // 创建searcher对象
            searcher = Searcher.newWithFileOnly(dbPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取IP地址归属地
     */
    public static String getCityInfo(String ip) {
        if (searcher == null || ip == null) {
            return "未知";
        }
        
        try {
            long startTime = System.nanoTime();
            String region = searcher.search(ip);
            long endTime = System.nanoTime();
            System.out.printf("IP: %s, 归属地: %s, 耗时: %f 微秒\n", 
                             ip, region, (endTime - startTime) / 1000000.0);
            return region;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "未知";
    }
    
    // 程序结束时释放资源
    public static void close() {
        if (searcher != null) {
            try {
                searcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2. 使用第三方API(在线解析)

public class IpLocationUtils {
    private static final String IP_API_URL = "https://api.ip2location.com/v2/?key=YOUR_API_KEY&ip=%s&package=WS3"
    
    /**
     * 通过第三方API获取IP归属地
     */
    public static String getIpLocation(String ip) {
        try {
            String url = String.format(IP_API_URL, ip);
            String result = HttpUtil.get(url);
            // 解析JSON结果
            JSONObject jsonObject = JSON.parseObject(result);
            String country = jsonObject.getString("country_name");
            String region = jsonObject.getString("region_name");
            String city = jsonObject.getString("city_name");
            return country + " " + region + " " + city;
        } catch (Exception e) {
            e.printStackTrace();
            return "未知";
        }
    }
}

四、创建统一的浏览器信息工具类

@Component
public class ClientInfoUtil {
    
    /**
     * 获取完整的客户端信息
     */
    public Map<String, Object> getClientInfo() {
        HttpServletRequest request = getCurrentRequest();
        if (request == null) {
            return Collections.emptyMap();
        }
        
        Map<String, Object> clientInfo = new HashMap<>();
        
        // 获取IP地址
        String ip = IpUtils.getIpAddr(request);
        clientInfo.put("ip", ip);
        
        // 获取IP归属地
        clientInfo.put("location", IpRegionUtils.getCityInfo(ip));
        
        // 获取并解析User-Agent
        String userAgentString = request.getHeader("User-Agent");
        Map<String, Object> browserInfo = BrowserUtils.parseBrowserInfo(userAgentString);
        clientInfo.putAll(browserInfo);
        
        // 获取其他有用信息
        clientInfo.put("sessionId", request.getSession().getId());
        clientInfo.put("requestUrl", request.getRequestURL().toString());
        clientInfo.put("referer", request.getHeader("Referer"));
        clientInfo.put("timestamp", System.currentTimeMillis());
        
        return clientInfo;
    }
    
    /**
     * 获取当前请求
     */
    private HttpServletRequest getCurrentRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        if (attributes instanceof ServletRequestAttributes) {
            return ((ServletRequestAttributes) attributes).getRequest();
        }
        return null;
    }
}

五、实际应用场景

1. 访问日志记录

@Aspect
@Component
@Slf4j
public class AccessLogAspect {
    
    @Autowired
    private ClientInfoUtil clientInfoUtil;
    
    @Pointcut("execution(* com.example.controller.*.*(..))")
    public void logPointCut() {}
    
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 获取客户端信息
        Map<String, Object> clientInfo = clientInfoUtil.getClientInfo();
        
        // 执行目标方法
        Object result = point.proceed();
        
        // 记录访问日志
        long endTime = System.currentTimeMillis();
        log.info("访问日志: {}", JSON.toJSONString(clientInfo));
        log.info("处理时间: {}ms", endTime - startTime);
        
        return result;
    }
}

2. 安全验证中间件

@Component
public class SecurityCheckFilter extends OncePerRequestFilter {
    
    @Autowired
    private ClientInfoUtil clientInfoUtil;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 
                                    FilterChain filterChain) throws ServletException, IOException {
        
        // 获取客户端信息
        Map<String, Object> clientInfo = clientInfoUtil.getClientInfo();
        
        // 进行安全检查(示例:检查是否是异常浏览器)
        String browser = (String) clientInfo.get("browser");
        if ("不支持的浏览器".equals(browser)) {
            response.setStatus(403);
            response.getWriter().write("不支持的浏览器,请使用主流浏览器访问");
            return;
        }
        
        // 继续过滤链
        filterChain.doFilter(request, response);
    }
}

六、注意事项

  1. 反向代理处理:在使用Nginx等反向代理时,需要正确配置代理头,确保能获取到真实IP
  2. 性能考虑:IP归属地查询可能影响性能,建议使用缓存
  3. 隐私保护:获取用户信息时要遵守相关隐私法规
  4. 依赖更新:UserAgentUtils库已停止维护,可考虑使用其他替代方案如yauaa
  5. 错误处理:网络请求和解析过程中要做好异常处理

通过以上方法,你可以在SpringBoot项目中全面获取和处理浏览器相关信息,为应用提供更丰富的功能和更好的用户体验。

到此这篇关于SpringBoot获取浏览器信息的多种实现方式的文章就介绍到这了,更多相关SpringBoot获取浏览器信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文