refactor: 添加 websocket 连接认证拦截器实现点对点指定用户发送消息;移除 easy-captcha 替换为 hutool-captcha验证码实现代码简化;重构认证接口控制层代码。
This commit is contained in:
@@ -1,41 +1,26 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.common.util.RequestUtils;
|
||||
import com.youlai.system.security.captcha.EasyCaptchaService;
|
||||
import com.youlai.system.model.dto.CaptchaResult;
|
||||
import com.youlai.system.model.dto.LoginResult;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import com.youlai.system.service.AuthService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Tag(name = "01.认证中心")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/auth")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
private final EasyCaptchaService easyCaptchaService;
|
||||
private final RedisTemplate redisTemplate;
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Operation(summary = "登录")
|
||||
@PostMapping("/login")
|
||||
@@ -43,46 +28,21 @@ public class AuthController {
|
||||
@Parameter(description = "用户名", example = "admin") @RequestParam String username,
|
||||
@Parameter(description = "密码", example = "123456") @RequestParam String password
|
||||
) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
username.toLowerCase().trim(),
|
||||
password
|
||||
);
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
// 生成token
|
||||
String accessToken = jwtTokenManager.createToken(authentication);
|
||||
LoginResult loginResult = LoginResult.builder()
|
||||
.tokenType("Bearer")
|
||||
.accessToken(accessToken)
|
||||
.build();
|
||||
LoginResult loginResult = authService.login(username, password);
|
||||
return Result.success(loginResult);
|
||||
}
|
||||
|
||||
@Operation(summary = "注销", security = {@SecurityRequirement(name = SecurityConstants.TOKEN_KEY)})
|
||||
@DeleteMapping("/logout")
|
||||
public Result logout(HttpServletRequest request) {
|
||||
String token = RequestUtils.resolveToken(request);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
Claims claims = jwtTokenManager.getTokenClaims(token);
|
||||
String jti = claims.get("jti", String.class);
|
||||
|
||||
Date expiration = claims.getExpiration();
|
||||
if (expiration != null) {
|
||||
// 有过期时间,在token有效时间内存入黑名单,超出时间移除黑名单节省内存占用
|
||||
long ttl = (expiration.getTime() - System.currentTimeMillis());
|
||||
redisTemplate.opsForValue().set(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + jti, null, ttl, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
// 无过期时间,永久加入黑名单
|
||||
redisTemplate.opsForValue().set(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + jti, null);
|
||||
}
|
||||
}
|
||||
SecurityContextHolder.clearContext();
|
||||
return Result.success("注销成功");
|
||||
public Result logout() {
|
||||
authService.logout();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "获取验证码")
|
||||
@GetMapping("/captcha")
|
||||
public Result getCaptcha() {
|
||||
CaptchaResult captcha = easyCaptchaService.getCaptcha();
|
||||
CaptchaResult captcha = authService.getCaptcha();
|
||||
return Result.success(captcha);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.youlai.system.common.constant.ExcelConstants;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.common.util.ExcelUtils;
|
||||
import com.youlai.system.util.ExcelUtils;
|
||||
import com.youlai.system.common.annotation.PreventDuplicateSubmit;
|
||||
import com.youlai.system.listener.easyexcel.UserImportListener;
|
||||
import com.youlai.system.model.vo.UserImportVO;
|
||||
@@ -128,8 +128,8 @@ public class SysUserController {
|
||||
|
||||
@Operation(summary = "获取当前登录用户信息", security = {@SecurityRequirement(name = "Authorization")})
|
||||
@GetMapping("/me")
|
||||
public Result<UserInfoVO> getUserLoginInfo() {
|
||||
UserInfoVO userInfoVO = userService.getUserLoginInfo();
|
||||
public Result<UserInfoVO> getCurrentUserInfo() {
|
||||
UserInfoVO userInfoVO = userService.getCurrentUserInfo();
|
||||
return Result.success(userInfoVO);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.youlai.system.controller.demo;
|
||||
|
||||
import com.youlai.system.common.result.Result;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.messaging.handler.annotation.DestinationVariable;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* WebSocket 测试控制器
|
||||
*
|
||||
@@ -24,28 +23,35 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@Slf4j
|
||||
public class WebsocketController {
|
||||
|
||||
private final SimpMessagingTemplate messagingTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* 广播发送消息
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
@MessageMapping("/sendToAll")
|
||||
@SendTo("/topic/all")
|
||||
@SendTo("/topic/notice")
|
||||
public String sendToAll(String message) {
|
||||
// 处理消息
|
||||
return "Hello, " + message + "!";
|
||||
return "System Notice: " + message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点对点发送消息
|
||||
* <p>
|
||||
* 模拟 张三 给 李四 发送消息场景
|
||||
*
|
||||
* @param principal 当前用户
|
||||
* @param username 接收消息的用户
|
||||
* @param message 消息内容
|
||||
*/
|
||||
// 处理发送到"/app/sendToUser/{username}"的消息
|
||||
@MessageMapping("/sendToUser/{username}")
|
||||
// 将消息处理器的返回值发送到指定用户
|
||||
@SendTo("/queue/user")
|
||||
public String sendToUser(@DestinationVariable("username") String username, String message) {
|
||||
// 处理消息
|
||||
return "Hello, " + username + ", your message is: " + message;
|
||||
//@SendToUser(value = "/queue/greeting")
|
||||
public void sendToUser(Principal principal, @DestinationVariable String username, String message) {
|
||||
log.info("sender:{};receiver:{}", username, principal.getName());
|
||||
messagingTemplate.convertAndSendToUser(username, "/queue/greeting", "Hello," + message);
|
||||
/// return "Hello, " + message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user