This commit is contained in:
xinsin 2023-06-06 00:27:32 +08:00
parent af5fe0c8c0
commit 2d9d863efa
7 changed files with 277 additions and 1 deletions

View File

@ -132,6 +132,10 @@
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -3,9 +3,11 @@ package top.xinsin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@MapperScan("top.xinsin.mapper")
@EnableScheduling
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);

View File

@ -0,0 +1,22 @@
package top.xinsin.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import top.xinsin.controller.WebSocketController;
import top.xinsin.service.WebSocketService;
@Configuration
@EnableWebSocket
public class WebsocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Autowired
public void socketUserService(WebSocketService webSocketService){
WebSocketController.webSocketService= webSocketService;
}
}

View File

@ -0,0 +1,85 @@
package top.xinsin.controller;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.xinsin.service.WebSocketService;
import top.xinsin.util.R;
import java.io.IOException;
import java.net.http.WebSocket;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@Component
@ServerEndpoint(value = "/api/auth/websocket/{userId}")
@Slf4j
public class WebSocketController {
private static ConcurrentHashMap<String, WebSocketController> webSocketMap = new ConcurrentHashMap<>();
private Session session;
private String userId;
public static WebSocketService webSocketService;
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
this.userId = userId;
//加入map
webSocketMap.put(userId, this);
R<String> stringR = webSocketService.addVerify(userId);
sendMessageByUserId(userId, stringR);
}
@OnClose
public void onClose() {
//从map中删除
webSocketMap.remove(userId);
}
@OnMessage
public void onMessage(String message, Session session) {
sendMessageByUserId(userId,webSocketService.parseMessage(userId,message,webSocketMap));
}
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
error.printStackTrace();
}
/**
* 向客户端发送消息
*/
@SneakyThrows
public void sendMessage(String message) {
this.session.getBasicRemote().sendText(message);
}
/**
* 通过userId向客户端发送消息
*/
@SneakyThrows
public void sendMessageByUserId(String userId, R<?> message) {
if(webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(JSON.toJSONString(message));
}else{
log.error("用户{}不在线",userId);
}
}
@Scheduled(fixedRate = 10000)
public void verifyTime(){
List<String> expireTimes = webSocketService.getExpireTimes();
expireTimes.forEach(e -> {
if(webSocketMap.containsKey(e)){
webSocketMap.get(e).sendMessage(JSON.toJSONString(R.success(new JSONObject().fluentPut("info","当前登录用户已过期"))));
}
});
}
}

View File

@ -187,7 +187,7 @@ public class AccountService implements UserDetailsService {
Verify verify = new Verify(accountAndStoreAdmin.getCreateId(), authAccount.getId(), accountAndStoreAdmin.getCountdown());
int insert1 = verifyMapper.insert(verify);
if (insert1 == 1){
redisTemplate.opsForValue().set(String.valueOf(authAccount.getId()),authAccount.getUsername(),verify.getCountdown(), TimeUnit.SECONDS);
// redisTemplate.opsForValue().set(String.valueOf(authAccount.getId()),authAccount.getUsername(),verify.getCountdown(), TimeUnit.SECONDS);
return R.success(new JSONObject().fluentPut("status","添加该商户成功").fluentPut("nextVerificationTime",verify.getCountdown()));
}
}

View File

@ -0,0 +1,161 @@
package top.xinsin.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import top.xinsin.controller.WebSocketController;
import top.xinsin.mapper.VerifyMapper;
import top.xinsin.pojo.Verify;
import top.xinsin.util.HttpCodes;
import top.xinsin.util.R;
import top.xinsin.util.StringConstant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import static org.apache.naming.SelectorContext.prefix;
@Service
@Slf4j
public class WebSocketService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private VerifyMapper verifyMapper;
public R<String> addVerify(String userId){
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setKeySerializer(stringSerializer);
if (userId.equals("-114514")){
return R.success("检测为管理员登录");
}
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId);
Object o1 = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
System.out.println(o == null);
System.out.println(o1 == null);
if (o == null && o1 == null){
Verify verify = verifyMapper.selectOne(new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
if (verify != null){
if(userId.equals(String.valueOf(verify.getStoreId()))) {
redisTemplate.opsForValue().set(StringConstant.VERIFY_PRE + userId, String.valueOf(verify.getNum()), verify.getCountdown(), TimeUnit.SECONDS);
redisTemplate.opsForValue().set(StringConstant.VERIFY_PRE + userId + "_no", String.valueOf(verify.getNum()));
return R.success("已将该用户过期时间存入");
}
}
}else{
return R.success("当前用户已存在");
}
return R.failed(HttpCodes.HTTP_CODES500,"不存在该用户");
}
public R<JSONObject> parseMessage(String userId, String message, ConcurrentHashMap<String, WebSocketController> webSocketMap){
JSONObject parse = JSONObject.parse(message);
String type = (String) parse.get("type");
switch (type) {
case "ping" -> {
return ping(userId);
}
case "addVerifyInfo" -> {
return addVerifyInfo(userId, parse);
}
case "getTime" -> {
return getTime(userId);
}
case "confirmVerifyInfo" -> {
return confirmVerifyInfo(parse,webSocketMap);
}
}
return null;
}
private R<JSONObject> confirmVerifyInfo(JSONObject parse, ConcurrentHashMap<String, WebSocketController> webSocketMap) {
String verifyResult = String.valueOf(parse.get("verifyResult"));
String userId = String.valueOf(parse.get("userId"));
int i = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no")));
System.out.println(i);
Verify verify = new Verify();
verify.setVerifyResult(verifyResult);
verify.setNum(i + 1);
int update = verifyMapper.update(verify, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
if (update != 1){
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","信息修改失败"));
}
if (verifyResult.equals("false")){
if (webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(JSON.toJSONString(new JSONObject().fluentPut("info","管理员未同意你的验证信息,你可以重新进行验证")));
}
return R.success(new JSONObject().fluentPut("info","你已拒绝该商户的验证信息"));
}else{
if (webSocketMap.containsKey(userId)){
webSocketMap.get(userId).sendMessage(JSON.toJSONString(new JSONObject().fluentPut("info","管理员已同意你的验证信息,请重新登录")));
redisTemplate.delete(StringConstant.VERIFY_PRE + userId + "_no");
Verify verify1 = new Verify();
verify.setVerifyPhone("");
verify.setVerifyName("");
verifyMapper.update(verify1, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
}
return R.success(new JSONObject().fluentPut("info","你已同意该商户的验证信息"));
}
}
private R<JSONObject> getTime(String userId) {
Long expire = redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId);
assert expire != null;
if (expire.equals(-2L)){
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
if (o != null){
return R.success(new JSONObject().fluentPut("info","当前用户登录已过期"));
}
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","没有该用户登录信息"));
}else{
return R.success(new JSONObject().fluentPut("info",expire));
}
}
private R<JSONObject> addVerifyInfo(String userId, JSONObject parse) {
Long expire = redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId);
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
assert expire != null;
if (expire.equals(-2L) && o != null){
Object verifyName = parse.get("verifyName");
Object verifyPhone = parse.get("verifyPhone");
Verify verify = new Verify();
verify.setVerifyName(String.valueOf(verifyName));
verify.setVerifyPhone(String.valueOf(verifyPhone));
int update = verifyMapper.update(verify, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
return update == 1 ? R.success(new JSONObject().fluentPut("info","验证信息添加成功,请耐心等待管理员审核")) : R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","添加验证信息失败"));
}
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","当前用户还未过期或者未登陆过"));
}
private R<JSONObject> ping(String userId) {
return R.success(new JSONObject().fluentPut("info","pong").fluentPut("time",redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId)));
}
public List<String> getExpireTimes(){
List<String> expireUser = new ArrayList<>();
Set<String> keys = redisTemplate.keys(prefix.concat(StringConstant.VERIFY_PRE + "*"));
assert keys != null;
keys.forEach(e -> {
if (Objects.equals(redisTemplate.getExpire(e), -1L)){
expireUser.add(e);
redisTemplate.delete(e);
}else if (Objects.equals(redisTemplate.getExpire(e),-2L)){
redisTemplate.delete(e);
}
});
log.info("{}",keys);
return expireUser;
}
}

View File

@ -5,4 +5,6 @@ public class StringConstant {
public static final String EMAIL_REGEX = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
public static final String USERNAME_REGEX = "[A-Za-z0-9_\\-一-龥]+";
public static final String ID_REGEX = "[0-9]*";
public static final String VERIFY_PRE = "verify_";
}