From f6f3df18ea57ea4128fcccf3282e1520e867c631 Mon Sep 17 00:00:00 2001
From: zj <1772600164@qq.com>
Date: Mon, 29 Jul 2024 13:49:22 +0800
Subject: [PATCH] 1
---
websocketSerivce/src/main/java/org/example/controller/Login.java | 89 ++++++
websocketSerivce/src/main/java/org/example/pojo/User.java | 63 ++++
websocketSerivce/pom.xml | 6
websocketSerivce/src/main/java/org/example/dao/ConfigCurrencyMapper.java | 16 +
websocketSerivce/src/main/java/org/example/pojo/Log.java | 27 +
websocketSerivce/src/main/java/org/example/controller/AdminLogin.java | 56 ++++
websocketSerivce/src/main/java/org/example/util/IpAddressUtil.java | 259 ++++++++++++++++++
websocketSerivce/src/main/java/org/example/dao/LogMapper.java | 16 +
websocketSerivce/src/main/java/org/example/websocket/controller/ReceptionController.java | 1
websocketSerivce/src/main/java/org/example/util/RedisUtil.java | 18 +
websocketSerivce/src/main/java/org/example/pojo/ConfigCurrency.java | 23 +
websocketSerivce/src/main/java/org/example/util/LoginInterceptor.java | 43 +++
websocketSerivce/src/main/java/org/example/pojo/vo/SaveConfigVo.java | 28 ++
websocketSerivce/src/main/java/org/example/util/WebMvcConfig.java | 21 +
websocketSerivce/src/main/java/org/example/controller/UserController.java | 71 +++++
websocketSerivce/src/main/java/org/example/util/MD5Util.java | 50 +++
websocketSerivce/src/main/java/org/example/dao/serServiceMapper.java | 10
websocketSerivce/src/main/java/org/example/server/impl/UserServiceImpl.java | 19 +
websocketSerivce/src/main/java/org/example/server/UserService.java | 9
websocketSerivce/src/main/resources/ip/csdn-ip2region.xdb | 0
20 files changed, 825 insertions(+), 0 deletions(-)
diff --git a/websocketSerivce/pom.xml b/websocketSerivce/pom.xml
index 7e3fbed..6935c06 100644
--- a/websocketSerivce/pom.xml
+++ b/websocketSerivce/pom.xml
@@ -126,6 +126,12 @@
<artifactId>logging-interceptor</artifactId>
<version>4.9.3</version>
</dependency>
+ <!-- IP地址转归属地 -->
+ <dependency>
+ <groupId>org.lionsoul</groupId>
+ <artifactId>ip2region</artifactId>
+ <version>2.6.4</version>
+ </dependency>
</dependencies>
<build>
<finalName>websocketSerivce</finalName>
diff --git a/websocketSerivce/src/main/java/org/example/controller/AdminLogin.java b/websocketSerivce/src/main/java/org/example/controller/AdminLogin.java
new file mode 100644
index 0000000..59fd45c
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/controller/AdminLogin.java
@@ -0,0 +1,56 @@
+package org.example.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.example.common.ServerResponse;
+import org.example.pojo.User;
+import org.example.server.impl.UserServiceImpl;
+import org.example.util.MD5Util;
+import org.example.util.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.Date;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:42
+ **/
+@RestController
+@RequestMapping("/admin")
+public class AdminLogin {
+
+ @Autowired
+ private UserServiceImpl userService;
+
+ @PostMapping("/login")
+ public ServerResponse saveUser(@RequestParam("account") int account
+ , @RequestParam("password") String password) {
+
+ User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount, account).eq(User::getIsRoot,1));
+ if(null == user){
+ return ServerResponse.createBySuccessMsg("管理员账号不存在");
+ }
+
+ if (!MD5Util.verify(password, user.getPassword())) {
+ return ServerResponse.createBySuccessMsg("密码错误");
+ }
+ String token = generateToken();
+ RedisUtil.set(user.getAccount(),token);
+ return ServerResponse.createBySuccess(token);
+ }
+
+ // 生成指定长度的随机 token
+ public static String generateToken() {
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] token = new byte[16];
+ secureRandom.nextBytes(token);
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(token);
+ }
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/controller/Login.java b/websocketSerivce/src/main/java/org/example/controller/Login.java
new file mode 100644
index 0000000..302f805
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/controller/Login.java
@@ -0,0 +1,89 @@
+package org.example.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.example.common.ServerResponse;
+import org.example.dao.LogMapper;
+import org.example.pojo.Log;
+import org.example.pojo.User;
+import org.example.server.UserService;
+import org.example.server.impl.UserServiceImpl;
+import org.example.util.IpAddressUtil;
+import org.example.util.MD5Util;
+import org.example.util.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.Date;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:17
+ **/
+@RestController
+@RequestMapping("/login")
+public class Login {
+
+ @Autowired
+ private UserServiceImpl userService;
+
+ @Autowired
+ private LogMapper logMapper;
+
+ @PostMapping("/login")
+ public ServerResponse saveUser(@RequestParam("account") String account
+ , @RequestParam("password") String password, HttpServletRequest request) {
+
+ User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getAccount, account));
+ if(null == user){
+ return ServerResponse.createBySuccessMsg("用户不存在");
+ }
+
+ if (!MD5Util.verify(password, user.getPassword())) {
+ return ServerResponse.createBySuccessMsg("密码错误");
+ }
+
+ //判断是否锁定
+ if(user.getIsLock() == 1){
+ return ServerResponse.createBySuccessMsg("账号已被锁定");
+ }
+
+ //判断是否到期
+ if(new Date().after(user.getEndTime())){
+ return ServerResponse.createBySuccessMsg("账号已到期");
+ }
+
+
+ String token = generateToken();
+ RedisUtil.set(user.getAccount(),token);
+
+ String ip = IpAddressUtil.getIpAddress(request);
+ String address = null;
+ address = IpAddressUtil.getIpPossessionByFile(ip);
+ if(null == address){
+ address = IpAddressUtil.getIpAddressByOnline(ip);
+ }
+ Log log = new Log();
+ log.setIp(ip);
+ log.setAccount(account);
+ log.setLoginTime(new Date());
+ log.setAddress(address);
+ logMapper.insert(log);
+
+ return ServerResponse.createBySuccess(token);
+ }
+
+ // 生成指定长度的随机 token
+ public static String generateToken() {
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] token = new byte[16];
+ secureRandom.nextBytes(token);
+ return Base64.getUrlEncoder().withoutPadding().encodeToString(token);
+ }
+}
diff --git a/websocketSerivce/src/main/java/org/example/controller/UserController.java b/websocketSerivce/src/main/java/org/example/controller/UserController.java
new file mode 100644
index 0000000..e37b31b
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/controller/UserController.java
@@ -0,0 +1,71 @@
+package org.example.controller;
+
+import org.example.common.ServerResponse;
+import org.example.dao.ConfigCurrencyMapper;
+import org.example.pojo.ConfigCurrency;
+import org.example.pojo.User;
+import org.example.pojo.vo.SaveConfigVo;
+import org.example.server.impl.UserServiceImpl;
+import org.example.util.MD5Util;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 10:47
+ **/
+@RestController
+@RequestMapping("/user")
+public class UserController {
+
+ @Autowired
+ private ConfigCurrencyMapper currencyMapper;
+
+ @Autowired
+ private UserServiceImpl userService;
+
+ @PostMapping("/saveConfig")
+ public ServerResponse saveConfig(SaveConfigVo saveConfigVo) {
+ saveConfigVo.getCurrencyList().forEach(f->{
+ ConfigCurrency currency = new ConfigCurrency();
+ currency.setUserId(saveConfigVo.getUserId());
+ currency.setCurrency(f.getCurrency());
+ currency.setBuy(f.getBuy());
+ currency.setSell(f.getSell());
+ currencyMapper.insert(currency);
+ });
+ return ServerResponse.createBySuccess();
+ }
+
+ @PostMapping("/saveUser")
+ public ServerResponse saveUser(User user) {
+ user.setPassword(MD5Util.encrypt(user.getPassword()));
+ userService.save(user);
+ return ServerResponse.createBySuccess();
+ }
+
+ @PostMapping("/deleteUser")
+ public ServerResponse deleteUser(@RequestParam("id") int id) {
+ User byId = userService.getById(id);
+ if(null == byId){
+ return ServerResponse.createByErrorMsg("用户不存在");
+ }
+ userService.removeById(id);
+ return ServerResponse.createBySuccess();
+ }
+
+ @PostMapping("/updateUser")
+ public ServerResponse deleteUser(User user) {
+ User byId = userService.getById(user.getId());
+ if(null == byId){
+ return ServerResponse.createByErrorMsg("用户不存在");
+ }
+ user.setPassword(MD5Util.encrypt(user.getPassword()));
+ userService.updateById(user);
+ return ServerResponse.createBySuccess();
+ }
+}
diff --git a/websocketSerivce/src/main/java/org/example/dao/ConfigCurrencyMapper.java b/websocketSerivce/src/main/java/org/example/dao/ConfigCurrencyMapper.java
new file mode 100644
index 0000000..bdab070
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/dao/ConfigCurrencyMapper.java
@@ -0,0 +1,16 @@
+package org.example.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.example.pojo.ConfigCurrency;
+import org.example.pojo.vo.SaveConfigVo;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 10:46
+ **/
+@Mapper
+public interface ConfigCurrencyMapper extends BaseMapper<ConfigCurrency> {
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/dao/LogMapper.java b/websocketSerivce/src/main/java/org/example/dao/LogMapper.java
new file mode 100644
index 0000000..32fd7d6
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/dao/LogMapper.java
@@ -0,0 +1,16 @@
+package org.example.dao;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:46
+ **/
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import lombok.Data;
+import org.apache.ibatis.annotations.Mapper;
+import org.example.pojo.Log;
+
+@Mapper
+public interface LogMapper extends BaseMapper<Log> {
+}
diff --git a/websocketSerivce/src/main/java/org/example/dao/serServiceMapper.java b/websocketSerivce/src/main/java/org/example/dao/serServiceMapper.java
new file mode 100644
index 0000000..c90252f
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/dao/serServiceMapper.java
@@ -0,0 +1,10 @@
+package org.example.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.example.pojo.User;
+
+@Mapper
+public interface serServiceMapper extends BaseMapper<User> {
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/pojo/ConfigCurrency.java b/websocketSerivce/src/main/java/org/example/pojo/ConfigCurrency.java
new file mode 100644
index 0000000..03a5773
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/pojo/ConfigCurrency.java
@@ -0,0 +1,23 @@
+package org.example.pojo;
+
+import lombok.Data;
+import org.example.pojo.vo.SaveConfigVo;
+
+import java.util.List;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 10:46
+ **/
+@Data
+public class ConfigCurrency {
+
+ private Integer userId;
+
+ private String currency;
+
+ private String buy;
+
+ private String sell;
+}
diff --git a/websocketSerivce/src/main/java/org/example/pojo/Log.java b/websocketSerivce/src/main/java/org/example/pojo/Log.java
new file mode 100644
index 0000000..c8bf1c0
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/pojo/Log.java
@@ -0,0 +1,27 @@
+package org.example.pojo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:45
+ **/
+@Data
+public class Log {
+
+ private Integer id;
+
+ private String account;
+
+ private Date loginTime;
+
+ private String ip;
+
+ private String address;
+
+
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/pojo/User.java b/websocketSerivce/src/main/java/org/example/pojo/User.java
new file mode 100644
index 0000000..a6c3cc9
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/pojo/User.java
@@ -0,0 +1,63 @@
+package org.example.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.sql.Date;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:06
+ **/
+@Data
+public class User {
+
+ @TableId(type = IdType.AUTO)
+ /**
+ * id
+ */
+ private Integer id;
+
+ /**
+ * 账号
+ */
+ private String account;
+
+ /**
+ * 密码
+ */
+ private String password;
+
+ /**
+ * 是否管理员 0 否 1 是
+ */
+ private Integer isRoot;
+
+ /**
+ * 添加时间
+ */
+ private Date addTime;
+
+ /**
+ * 到期时间
+ */
+ private Date endTime;
+
+ /**
+ * 是否显示 0 是 1 否
+ */
+ private Integer isShow;
+
+ /**
+ * 是否锁定 0 否 1 是
+ */
+ private Integer isLock;
+
+ /**
+ * 设备数量
+ */
+ private Integer deviceNumber;
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/pojo/vo/SaveConfigVo.java b/websocketSerivce/src/main/java/org/example/pojo/vo/SaveConfigVo.java
new file mode 100644
index 0000000..3f1197b
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/pojo/vo/SaveConfigVo.java
@@ -0,0 +1,28 @@
+package org.example.pojo.vo;
+
+import lombok.Data;
+import org.example.pojo.ConfigCurrency;
+
+import java.util.List;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 10:40
+ **/
+@Data
+public class SaveConfigVo {
+
+ private Integer userId;
+
+ private List<ConfigCurrencyVo> currencyList;
+
+ @Data
+ public class ConfigCurrencyVo{
+ private String currency;
+
+ private String buy;
+
+ private String sell;
+ }
+}
diff --git a/websocketSerivce/src/main/java/org/example/server/UserService.java b/websocketSerivce/src/main/java/org/example/server/UserService.java
new file mode 100644
index 0000000..3729325
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/server/UserService.java
@@ -0,0 +1,9 @@
+package org.example.server;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:08
+ **/
+public interface UserService {
+}
diff --git a/websocketSerivce/src/main/java/org/example/server/impl/UserServiceImpl.java b/websocketSerivce/src/main/java/org/example/server/impl/UserServiceImpl.java
new file mode 100644
index 0000000..975e66b
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/server/impl/UserServiceImpl.java
@@ -0,0 +1,19 @@
+package org.example.server.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.example.dao.CurrencyMapper;
+import org.example.dao.serServiceMapper;
+import org.example.pojo.Currency;
+import org.example.pojo.User;
+import org.example.server.CurrencySerivce;
+import org.example.server.UserService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:08
+ **/
+@Service
+public class UserServiceImpl extends ServiceImpl<serServiceMapper, User> implements UserService {
+}
diff --git a/websocketSerivce/src/main/java/org/example/util/IpAddressUtil.java b/websocketSerivce/src/main/java/org/example/util/IpAddressUtil.java
new file mode 100644
index 0000000..631c373
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/util/IpAddressUtil.java
@@ -0,0 +1,259 @@
+package org.example.util;
+
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.lionsoul.ip2region.xdb.Searcher;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.ServerHttpRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:50
+ **/
+
+@Slf4j
+public class IpAddressUtil {
+
+ // ip2region.xdb 文件地址常量(本地xdb文件路径)
+ public static String XDB_PATH = "D:\\项目\\demo\\websocketSerivce\\src\\main\\resources\\ip\\csdn-ip2region.xdb";
+
+ /**
+ * 获取IP地址:
+ */
+ public static String getIpAddress(HttpServletRequest request) {
+ String ipAddress = null;
+ try {
+ ipAddress = request.getHeader("X-Forwarded-For");
+ if (ipAddress != null && ipAddress.length() != 0 && !"unknown".equalsIgnoreCase(ipAddress)) {
+ // 多次反向代理后会有多个ip值,第一个ip才是真实ip
+ if (ipAddress.contains(",")) {
+ ipAddress = ipAddress.split(",")[0];
+ }
+ }
+ if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+ ipAddress = request.getHeader("Proxy-Client-IP");
+ }
+ if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+ ipAddress = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+ ipAddress = request.getHeader("HTTP_CLIENT_IP");
+ }
+ if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
+ ipAddress = request.getRemoteAddr();
+ }
+ } catch (Exception e) {
+ log.error("获取IP地址异常,{}", e.getMessage());
+ }
+ return ipAddress;
+ }
+
+ /**
+ * 获取mac地址
+ */
+ public static String getMacIpAddress() {
+ try {
+ InetAddress inetAddress = InetAddress.getLocalHost();
+ byte[] macAddressBytes = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
+ // 将mac地址拼装成String
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < macAddressBytes.length; i++) {
+ if (i != 0) {
+ sb.append("-");
+ }
+ // mac[i] & 0xFF 是为了把byte转化为正整数
+ String s = Integer.toHexString(macAddressBytes[i] & 0xFF);
+ sb.append(s.length() == 1 ? 0 + s : s);
+ }
+ return sb.toString().trim().toUpperCase();
+ } catch (Exception e) {
+ log.error("Mac获取IP地址异常,{}", e.getMessage());
+ }
+ return "";
+ }
+
+ /**
+ * 方法一:完全基于ip2region.xdb文件,对用户ip地址进行转换
+ * 注:并发调用时,每个线程需创建一个独立的searcher对象 单独使用。
+ */
+ public static String getIpPossessionByFile(String ip) {
+ if (StringUtils.isNotEmpty(ip)) {
+ try {
+ // 1、创建 searcher 对象
+ Searcher searcher = Searcher.newWithFileOnly(XDB_PATH);
+ // 2、查询
+ long sTime = System.nanoTime();
+ String region = searcher.search(ip);
+ long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
+ region = region.replace("|0", "");
+ //log.info("{地区: {}, IO操作数: {}, 耗时: {} μs}", region, searcher.getIOCount(), cost);
+ return region;
+ } catch (Exception e) {
+ log.error("获取IP地址异常:{} ", e.getMessage());
+ throw new RuntimeException("获取IP地址异常");
+ }
+ }
+ return "未知";
+ }
+
+ /**
+ * 方法二:缓存 VectorIndex 索引,对用户ip地址进行转换
+ * 注:每个线程需要单独创建一个独立的 Searcher 对象,但是都共享全局变量 vIndex 缓存。
+ */
+ public static String getCityInfoByVectorIndex(String ip) {
+ if (StringUtils.isNotEmpty(ip)) {
+ try {
+ // 1、从 XDB_PATH 中预先加载 VectorIndex 缓存,并且作为全局变量,后续反复使用。
+ byte[] vIndex = Searcher.loadVectorIndexFromFile(XDB_PATH);
+ // 2、使用全局的 vIndex 创建带 VectorIndex 缓存的查询对象。
+ Searcher searcher = Searcher.newWithVectorIndex(XDB_PATH, vIndex);
+ // 3、查询
+ long sTime = System.nanoTime();
+ String region = searcher.search(ip);
+ long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
+ region = region.replace("|0", "");
+ //log.info("{地区: {}, IO操作数: {}, 耗时: {} μs}", region, searcher.getIOCount(), cost);
+ return region;
+ } catch (Exception e) {
+ log.error("获取IP地址异常:{} ", e.getMessage());
+ throw new RuntimeException("获取IP地址异常");
+ }
+ }
+ return "未知";
+ }
+
+ /**
+ * 方法三:缓存整个 xdb 数据,对用户ip地址进行转换
+ * 注:并发使用时,用整个 xdb 数据缓存创建的查询对象可以安全的用于并发,也就是你可以把这个 searcher 对象做成全局对象去跨线程访问。
+ */
+ public static String getCityInfoByMemorySearch(String ip) {
+ if (StringUtils.isNotEmpty(ip)) {
+ try {
+ // 1、从 XDB_PATH 加载整个 xdb 到内存。
+ byte[] cBuff = Searcher.loadContentFromFile(XDB_PATH);
+ // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
+ Searcher searcher = Searcher.newWithBuffer(cBuff);
+ // 3、查询
+ long sTime = System.nanoTime();
+ String region = searcher.search(ip);
+ long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
+ region = region.replace("|0", "");
+ //log.info("{地区: {}, IO操作数: {}, 耗时: {} μs}", region, searcher.getIOCount(), cost);
+ return region;
+ } catch (Exception e) {
+ log.error("获取IP地址异常:{} ", e.getMessage());
+ throw new RuntimeException("获取IP地址异常");
+ }
+ }
+ return "未知";
+ }
+
+ /**
+ * 方法四:在线获取IP地址
+ * 注:通过别人或者官网提供的API接口去实现查询的功能,弊端就是特别依赖别人的服务器,一旦服务器宕机就无法访问了。
+ */
+ public static String getIpAddressByOnline(String ip) {
+
+ try {
+ //1、创建 URLConnction
+ URL url = new URL("http://ip-api.com/json/" + ip + "?lang=zh-CN");
+
+ //2、设置connection的属性
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(20000);
+ connection.setReadTimeout(20000);
+ connection.setRequestProperty("content-type", "application/json; charset=utf-8");
+
+ //3.连接
+ connection.connect();
+
+ //4.获取内容
+ InputStream inputStream = connection.getInputStream();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
+ String line;
+ StringBuilder sb = new StringBuilder();
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ }
+ br.close();
+ //System.out.println(sb);
+
+ String str = sb.toString();
+ if (StringUtils.isNotEmpty(str)) {
+ // string转map
+ Gson gson = new Gson();
+ Map<String, Object> map = new HashMap<>();
+ map = gson.fromJson(str, map.getClass());
+ String country = (String) map.get("country");
+ String city = (String) map.get("city");
+ String regionName = (String) map.get("regionName");
+ //log.info("【国家】{},【城市】{},【地区】{}", country, city, regionName);
+ return country + "|" + city + "|" + regionName;
+ }
+ } catch (Exception e) {
+ log.error("在线查询IP地址异常,{}", e.getMessage());
+ throw new RuntimeException("在线查询IP地址异常");
+ }
+ return null;
+ }
+
+ /**
+ * 根据IP地址 获取归属地
+ */
+ public static String getIpPossession(String ipAddress) {
+ if (StringUtils.isNotEmpty(ipAddress)) {
+ ipAddress = ipAddress.replace("|", " ");
+ String[] cityList = ipAddress.split(" ");
+ if (cityList.length > 0) {
+ // 国内的显示到具体的省
+ if ("中国".equals(cityList[0])) {
+ if (cityList.length > 1) {
+ return cityList[1];
+ }
+ }
+ // 国外显示到国家
+ return cityList[0];
+ }
+ }
+ return "未知";
+ }
+
+ public static void main(String[] args) {
+
+ String ip = "183.162.252.0";// 国内IP
+ String abroadIp = "48.119.248.100"; // 国外IP
+
+ System.out.println("方法一(国内):" + getIpPossessionByFile(ip));
+ System.out.println("方法二(国内):" + getCityInfoByVectorIndex(ip));
+ System.out.println("方法三(国内):" + getCityInfoByMemorySearch(ip));
+ System.out.println("方法四(国内):" + getIpAddressByOnline(ip));
+
+ System.out.println("方法一(国外):" + getIpPossessionByFile(abroadIp));
+ System.out.println("方法二(国外):" + getCityInfoByVectorIndex(abroadIp));
+ System.out.println("方法三(国外):" + getCityInfoByMemorySearch(abroadIp));
+ System.out.println("方法四(国外):" + getIpAddressByOnline(abroadIp));
+
+ //System.out.println("归属地(国内):" + getIpPossession(getCityInfoByVectorIndex(ip)));
+ //System.out.println("归属地(国外):" + getIpPossession(getCityInfoByVectorIndex(abroadIp)));
+
+ }
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/util/LoginInterceptor.java b/websocketSerivce/src/main/java/org/example/util/LoginInterceptor.java
new file mode 100644
index 0000000..e69c348
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/util/LoginInterceptor.java
@@ -0,0 +1,43 @@
+package org.example.util;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:15
+ **/
+public class LoginInterceptor implements HandlerInterceptor {
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+
+ HttpSession session = request.getSession();
+
+ // 假设登录状态信息保存在 session 中,这里简单示例,实际项目中可能会有自己的登录状态判断逻辑
+ if (session.getAttribute("loggedInUser") != null) {
+ // 已登录,允许请求继续
+ return true;
+ } else {
+ // 未登录,返回未授权错误码或重定向到登录页
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 返回 401 未授权状态码
+ return false;
+ }
+ }
+
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+ ModelAndView modelAndView) throws Exception {
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
+ Exception ex) throws Exception {
+ }
+}
\ No newline at end of file
diff --git a/websocketSerivce/src/main/java/org/example/util/MD5Util.java b/websocketSerivce/src/main/java/org/example/util/MD5Util.java
new file mode 100644
index 0000000..7ed1f53
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/util/MD5Util.java
@@ -0,0 +1,50 @@
+package org.example.util;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:22
+ **/
+public class MD5Util {
+ // 使用MD5算法对密码进行加密
+ public static String encrypt(String password) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] messageDigest = md.digest(password.getBytes());
+ BigInteger no = new BigInteger(1, messageDigest);
+ StringBuilder hashText = new StringBuilder(no.toString(16));
+ while (hashText.length() < 32) {
+ hashText.insert(0, "0");
+ }
+ return hashText.toString();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ // 校验输入的密码和加密后的密码是否匹配
+ public static boolean verify(String inputPassword, String hashedPassword) {
+ String hashedInputPassword = encrypt(inputPassword);
+ return hashedInputPassword.equals(hashedPassword);
+ }
+
+ // 示例用法
+ public static void main(String[] args) {
+ String originalPassword = "myPassword123";
+ String hashedPassword = encrypt(originalPassword);
+
+ // 模拟校验过程
+ String inputPassword = "myPassword123";
+ if (verify(inputPassword, hashedPassword)) {
+ System.out.println("Password Matched!");
+ } else {
+ System.out.println("Password Not Matched!");
+ }
+ }
+
+}
diff --git a/websocketSerivce/src/main/java/org/example/util/RedisUtil.java b/websocketSerivce/src/main/java/org/example/util/RedisUtil.java
index 8fb6808..e1c6022 100644
--- a/websocketSerivce/src/main/java/org/example/util/RedisUtil.java
+++ b/websocketSerivce/src/main/java/org/example/util/RedisUtil.java
@@ -90,6 +90,24 @@
}
}
+ // 设置 Token 的过期时间
+ public void setTokenExpiration(String token, int expirationInSeconds) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ jedis.expire(token, expirationInSeconds);
+ }
+
+ }
+
+ // 更新 Token 的过期时间
+ public void updateTokenExpiration(String token, int expirationInSeconds) {
+ try (Jedis jedis = jedisPool.getResource()) {
+ if (jedis.exists(token)) {
+ jedis.expire(token, expirationInSeconds);
+ }
+ }
+ }
+
+
public static void disconnect() {
jedisPool.close();
}
diff --git a/websocketSerivce/src/main/java/org/example/util/WebMvcConfig.java b/websocketSerivce/src/main/java/org/example/util/WebMvcConfig.java
new file mode 100644
index 0000000..13d51c1
--- /dev/null
+++ b/websocketSerivce/src/main/java/org/example/util/WebMvcConfig.java
@@ -0,0 +1,21 @@
+package org.example.util;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @program: demo
+ * @description:
+ * @create: 2024-07-29 11:15
+ **/
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(new LoginInterceptor())
+ .addPathPatterns("/**") // 拦截所有请求
+ .excludePathPatterns("/login", "/admin/login","/logout"); // 排除登录页和登出操作,防止死循环
+ }
+}
\ No newline at end of file
diff --git a/websocketSerivce/src/main/java/org/example/websocket/controller/ReceptionController.java b/websocketSerivce/src/main/java/org/example/websocket/controller/ReceptionController.java
index 4997f4b..e7ccbab 100644
--- a/websocketSerivce/src/main/java/org/example/websocket/controller/ReceptionController.java
+++ b/websocketSerivce/src/main/java/org/example/websocket/controller/ReceptionController.java
@@ -2,6 +2,7 @@
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
+import org.example.pojo.vo.SaveConfigVo;
import org.example.websocket.server.WsServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
diff --git a/websocketSerivce/src/main/resources/ip/csdn-ip2region.xdb b/websocketSerivce/src/main/resources/ip/csdn-ip2region.xdb
new file mode 100644
index 0000000..c78b792
--- /dev/null
+++ b/websocketSerivce/src/main/resources/ip/csdn-ip2region.xdb
Binary files differ
--
Gitblit v1.9.3