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/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); + + } + }