diff --git a/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java
new file mode 100644
index 0000000..501a252
--- /dev/null
+++ b/chaos_api_domain/src/main/java/cn/nopj/chaos_api/dto/FileUploadResponse.java
@@ -0,0 +1,13 @@
+package cn.nopj.chaos_api.dto;
+
+import lombok.Data;
+
+@Data
+public class FileUploadResponse {
+ private String fileName;
+ private String fileDownloadUri;
+ private String ossBucket;
+ private String fileOSSUri;
+ private String fileType;
+ private long size;
+}
diff --git a/chaos_api_interface/pom.xml b/chaos_api_interface/pom.xml
index 2616d64..10ccaa0 100644
--- a/chaos_api_interface/pom.xml
+++ b/chaos_api_interface/pom.xml
@@ -25,6 +25,7 @@
chaos_api_domain
${project.version}
+
diff --git a/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java
new file mode 100644
index 0000000..192405e
--- /dev/null
+++ b/chaos_api_interface/src/main/java/cn/nopj/chaos_api/service/ImageService.java
@@ -0,0 +1,15 @@
+package cn.nopj.chaos_api.service;
+
+
+import java.io.InputStream;
+
+public interface ImageService {
+
+ /**
+ * 上传图片
+ * @param fileName 文件名
+ * @param content 文件内容
+ * @return 文件路径
+ */
+ String uploadImage(String fileName, InputStream content);
+}
diff --git a/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java
new file mode 100644
index 0000000..abf5924
--- /dev/null
+++ b/chaos_api_service/src/main/java/cn/nopj/chaos_api/service/impl/ImageServiceImpl.java
@@ -0,0 +1,17 @@
+package cn.nopj.chaos_api.service.impl;
+
+import cn.nopj.chaos_api.service.ImageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.InputStream;
+
+@Slf4j
+@Service
+public class ImageServiceImpl implements ImageService {
+ @Override
+ public String uploadImage(String fileName, InputStream content) {
+ //todo 完成上传图片功能
+ return "";
+ }
+}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
index 17f98fb..363bcbe 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/config/jwt/JwtAuthenticationTokenFilter.java
@@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -17,6 +18,7 @@ import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
+import java.util.List;
/**
* JWT 登录授权过滤器
@@ -25,8 +27,6 @@ import java.io.IOException;
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
- @Autowired
- private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.tokenHeader}")
@@ -49,11 +49,19 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
log.info("username={}", username);
// 如果 Token 中有用户名但上下文中没有,说明是首次登录
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
- UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
+
// 验证 Token 是否有效
- if (jwtTokenUtil.validateToken(authToken, userDetails)) {
+ if (jwtTokenUtil.validateToken(authToken)) {
+
+ List authorityStrings = jwtTokenUtil.getAuthoritiesFromToken(authToken);
+
+ List authorities = authorityStrings.stream()
+ .map(SimpleGrantedAuthority::new)
+ .toList();
+ log.info("authorities: {}", authorities);
UsernamePasswordAuthenticationToken authentication =
- new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ new UsernamePasswordAuthenticationToken(username, null, authorities);
+
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java
new file mode 100644
index 0000000..8515fd9
--- /dev/null
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/HLSController.java
@@ -0,0 +1,20 @@
+package cn.nopj.chaos_api.controller;
+
+import cn.nopj.chaos_api.model.ApiResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/hls")
+public class HLSController {
+
+ @PreAuthorize("hasAuthority('admin')")
+ @GetMapping("/")
+ ApiResult getHLS(){
+ return ApiResult.success("HLS is radar");
+ }
+}
\ No newline at end of file
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java
new file mode 100644
index 0000000..bb06729
--- /dev/null
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/controller/ImageController.java
@@ -0,0 +1,24 @@
+package cn.nopj.chaos_api.controller;
+
+import cn.nopj.chaos_api.model.ApiResult;
+import cn.nopj.chaos_api.service.ImageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/image")
+public class ImageController {
+ @Autowired
+ private ImageService imageService;
+
+ @RequestMapping("/upload")
+ ApiResult uploadImage(@RequestParam("file") MultipartFile file) {
+ log.info("上传图片");
+ return ApiResult.success("上传成功");
+ }
+}
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
index b5d31dc..aba8d0d 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/service/impl/UserDetailsServiceImpl.java
@@ -3,6 +3,7 @@ package cn.nopj.chaos_api.service.impl;
import cn.nopj.chaos_api.domain.entity.User;
import cn.nopj.chaos_api.mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -15,6 +16,7 @@ import java.util.List;
import java.util.stream.Collectors;
@Service
+@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
@@ -30,6 +32,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
// 2. 查询该用户的权限信息 (角色 + 权限)
List authorities = userMapper.findAuthoritiesByUsername(username);
+ log.info("用户权限列表: {}", authorities);
// 3. 将权限字符串列表转换为 GrantedAuthority 集合
List grantedAuthorities = authorities.stream()
.map(SimpleGrantedAuthority::new)
diff --git a/chaos_api_web/src/main/java/cn/nopj/chaos_api/util/JwtTokenUtil.java b/chaos_api_web/src/main/java/cn/nopj/chaos_api/util/JwtTokenUtil.java
index 416935c..6f89c3d 100644
--- a/chaos_api_web/src/main/java/cn/nopj/chaos_api/util/JwtTokenUtil.java
+++ b/chaos_api_web/src/main/java/cn/nopj/chaos_api/util/JwtTokenUtil.java
@@ -6,12 +6,15 @@ import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
@Slf4j
@@ -53,10 +56,9 @@ public class JwtTokenUtil {
/**
* 验证 Token 是否有效
*/
- public boolean validateToken(String token, UserDetails userDetails) {
+ public boolean validateToken(String token) {
try {
- String username = getUsernameFromToken(token);
- return username != null && username.equals(userDetails.getUsername()) && !isTokenExpired(token);
+ return decodeToken(token) != null;
} catch (Exception e) {
return false;
}
@@ -69,10 +71,17 @@ public class JwtTokenUtil {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration * 1000);
+ List authorities = userDetails.getAuthorities()
+ .stream()
+ .map(GrantedAuthority::getAuthority)
+ .toList();
+
+
return JWT.create()
.withSubject(userDetails.getUsername())
.withIssuedAt(now)
.withExpiresAt(expiryDate)
+ .withClaim("authorities", authorities)
.sign(algorithm);
}
@@ -86,4 +95,34 @@ public class JwtTokenUtil {
}
}
+
+ /**
+ * 解析 Token
+ * @param token Token
+ * @return 解析后的 Token
+ */
+ private DecodedJWT decodeToken(String token) {
+ try {
+ return JWT.decode(token);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+
+ /**
+ * 从 Token 中获取权限列表
+ * @param token Token
+ * @return 权限列表
+ */
+ public List getAuthoritiesFromToken(String token){
+ DecodedJWT decodedJWT = decodeToken(token);
+ if (decodedJWT == null){
+ return null;
+ }
+ return decodedJWT.getClaim("authorities")
+ .asList(String.class);
+
+ }
+
}