From 03a37dd51e691940f379fe1f01946e356307611b Mon Sep 17 00:00:00 2001 From: panxuejie <15855548138@163.com> Date: Wed, 14 Jan 2026 09:59:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E9=89=B4=E6=9D=83=E9=9B=86=E4=B8=AD?= =?UTF-8?q?=E5=88=B0=E7=BD=91=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/FeignAuthInterceptor.java | 55 ++++++----- .../tacit/admin/config/SecurityConfig.java | 92 +++++-------------- .../tacit/app/config/AppSecurityConfig.java | 67 ++++---------- .../app/service/impl/UserServiceImpl.java | 3 + 4 files changed, 79 insertions(+), 138 deletions(-) diff --git a/common/common-feign/src/main/java/com/tacit/common/feign/interceptor/FeignAuthInterceptor.java b/common/common-feign/src/main/java/com/tacit/common/feign/interceptor/FeignAuthInterceptor.java index 29c4865..b31d1c3 100644 --- a/common/common-feign/src/main/java/com/tacit/common/feign/interceptor/FeignAuthInterceptor.java +++ b/common/common-feign/src/main/java/com/tacit/common/feign/interceptor/FeignAuthInterceptor.java @@ -1,6 +1,7 @@ package com.tacit.common.feign.interceptor; import com.tacit.common.constant.CommonConstant; +import com.tacit.common.utils.SecurityUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -20,44 +21,56 @@ public class FeignAuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { - // 从当前线程获取认证信息 - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + // 先尝试从SecurityUtils获取用户信息(推荐方式) + Long userId = SecurityUtils.getCurrentUserId(); + String username = SecurityUtils.getCurrentUsername(); + String role = SecurityUtils.getCurrentUserRole(); - if (authentication != null && !(authentication instanceof org.springframework.security.authentication.AnonymousAuthenticationToken)) { - // 获取用户名 - String username = authentication.getName(); + if (userId != null && username != null && role != null) { + // 传递用户信息头 + template.header("X-User-Id", String.valueOf(userId)); template.header("X-Username", username); - - // 获取角色信息 - authentication.getAuthorities().forEach(authority -> { - template.header("X-Role", authority.getAuthority().replace("ROLE_", "")); - }); + template.header("X-Role", role); } else { + // 从当前线程获取认证信息 + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && !(authentication instanceof org.springframework.security.authentication.AnonymousAuthenticationToken)) { + // 获取用户名 + String authUsername = authentication.getName(); + template.header("X-Username", authUsername); + + // 获取角色信息 + authentication.getAuthorities().forEach(authority -> { + template.header("X-Role", authority.getAuthority().replace("ROLE_", "")); + }); + } + // 从RequestContextHolder中获取请求信息(适用于非Feign调用场景) RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if (requestAttributes instanceof ServletRequestAttributes) { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; HttpServletRequest request = servletRequestAttributes.getRequest(); - // 传递JWT令牌 + // 传递JWT令牌(作为后备方案) String authorization = request.getHeader(CommonConstant.JWT_HEADER); if (authorization != null && authorization.startsWith(CommonConstant.JWT_PREFIX)) { template.header(CommonConstant.JWT_HEADER, authorization); } - // 传递用户上下文 - String userId = request.getHeader("X-User-Id"); - String username = request.getHeader("X-Username"); - String role = request.getHeader("X-Role"); + // 传递用户上下文头(如果有的话) + String requestUserId = request.getHeader("X-User-Id"); + String requestUsername = request.getHeader("X-Username"); + String requestRole = request.getHeader("X-Role"); - if (userId != null) { - template.header("X-User-Id", userId); + if (requestUserId != null) { + template.header("X-User-Id", requestUserId); } - if (username != null) { - template.header("X-Username", username); + if (requestUsername != null) { + template.header("X-Username", requestUsername); } - if (role != null) { - template.header("X-Role", role); + if (requestRole != null) { + template.header("X-Role", requestRole); } } } diff --git a/tacit-admin/src/main/java/com/tacit/admin/config/SecurityConfig.java b/tacit-admin/src/main/java/com/tacit/admin/config/SecurityConfig.java index 339f070..02b5cae 100644 --- a/tacit-admin/src/main/java/com/tacit/admin/config/SecurityConfig.java +++ b/tacit-admin/src/main/java/com/tacit/admin/config/SecurityConfig.java @@ -1,10 +1,10 @@ package com.tacit.admin.config; -import com.tacit.common.constant.CommonConstant; import com.tacit.common.utils.AesPasswordEncoder; -import com.tacit.common.utils.JwtUtils; -import com.tacit.common.redis.utils.RedisUtils; -import jakarta.annotation.Resource; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -22,10 +22,6 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Collections; import java.util.HashMap; @@ -35,9 +31,6 @@ import java.util.HashMap; @EnableMethodSecurity(prePostEnabled = true) @Slf4j public class SecurityConfig { - - @Resource - private RedisUtils redisUtils; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @@ -46,9 +39,8 @@ public class SecurityConfig { .cors(AbstractHttpConfigurer::disable) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth - .requestMatchers("/auth/login", "/auth/register","test/**", "/test/hello", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll() - .requestMatchers("/test/feign/**").authenticated() - .anyRequest().authenticated()) + // 所有请求都允许通过,鉴权由网关完成 + .anyRequest().permitAll()) .addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); @@ -59,62 +51,24 @@ public class SecurityConfig { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - // 先检查是否有JWT令牌(直接服务间调用时可能传递JWT) - String authorization = request.getHeader(CommonConstant.JWT_HEADER); - if (authorization != null && authorization.startsWith(CommonConstant.JWT_PREFIX)) { - String token = authorization.substring(CommonConstant.JWT_PREFIX.length()); - try { - // 验证JWT令牌 - if (JwtUtils.validateToken(token)) { - // 从令牌中获取用户信息 - Long userId = JwtUtils.getUserIdFromToken(token); - - // 构建Redis key:tacit:user:token:{userId} - String redisKey = CommonConstant.REDIS_KEY_TACIT_USER_TOKEN + userId; - - // 验证Redis中的令牌是否存在且匹配 - String redisToken = redisUtils.get(redisKey); - if (token.equals(redisToken)) { - String username = JwtUtils.getUsernameFromToken(token); - String role = JwtUtils.getRoleFromToken(token); - - // 创建认证对象 - User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); - - // 创建用户详情map,存储userId等信息 - HashMap userDetails = new HashMap<>(); - userDetails.put("userId", userId); - userDetails.put("username", username); - userDetails.put("role", role); - - var authentication = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); - authentication.setDetails(userDetails); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } - } catch (Exception e) { - log.error("JWT令牌验证失败: {}", e.getMessage()); - } - } else { - // 检查是否有用户上下文头(网关转发时添加) - String userIdStr = request.getHeader("X-User-Id"); - String username = request.getHeader("X-Username"); - String role = request.getHeader("X-Role"); + // 只从请求头中获取用户信息,不做鉴权 + String userIdStr = request.getHeader("X-User-Id"); + String username = request.getHeader("X-Username"); + String role = request.getHeader("X-Role"); - if (userIdStr != null && username != null && role != null) { - // 创建认证对象 - User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); - - // 创建用户详情map,存储userId等信息 - HashMap userDetails = new HashMap<>(); - userDetails.put("userId", Long.parseLong(userIdStr)); - userDetails.put("username", username); - userDetails.put("role", role); - - var authentication = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); - authentication.setDetails(userDetails); - SecurityContextHolder.getContext().setAuthentication(authentication); - } + if (userIdStr != null && username != null && role != null) { + // 创建认证对象 + User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); + + // 创建用户详情map,存储userId等信息 + HashMap userDetails = new HashMap<>(); + userDetails.put("userId", Long.parseLong(userIdStr)); + userDetails.put("username", username); + userDetails.put("role", role); + + var authentication = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); + authentication.setDetails(userDetails); + SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); diff --git a/tacit-app-api/src/main/java/com/tacit/app/config/AppSecurityConfig.java b/tacit-app-api/src/main/java/com/tacit/app/config/AppSecurityConfig.java index de1a78b..42b848b 100644 --- a/tacit-app-api/src/main/java/com/tacit/app/config/AppSecurityConfig.java +++ b/tacit-app-api/src/main/java/com/tacit/app/config/AppSecurityConfig.java @@ -1,11 +1,7 @@ package com.tacit.app.config; -import com.tacit.common.constant.CommonConstant; -import com.tacit.common.redis.utils.RedisUtils; import com.tacit.common.utils.AesPasswordEncoder; -import com.tacit.common.utils.JwtUtils; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -27,15 +23,13 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; @Configuration @EnableWebSecurity @EnableMethodSecurity(prePostEnabled = true) @Slf4j public class AppSecurityConfig { - - @Autowired - private RedisUtils redisUtils; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @@ -44,9 +38,8 @@ public class AppSecurityConfig { .cors(AbstractHttpConfigurer::disable) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth - .requestMatchers("/auth/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/user/info/**").permitAll() - .anyRequest().authenticated() - ) + // 所有请求都允许通过,鉴权由网关完成 + .anyRequest().permitAll()) .addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); @@ -57,45 +50,23 @@ public class AppSecurityConfig { return new OncePerRequestFilter() { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - // 先检查是否有JWT令牌(直接服务间调用时可能传递JWT) - String authorization = request.getHeader(CommonConstant.JWT_HEADER); - if (authorization != null && authorization.startsWith(CommonConstant.JWT_PREFIX)) { - String token = authorization.substring(CommonConstant.JWT_PREFIX.length()); - try { - // 验证JWT令牌 - if (JwtUtils.validateToken(token)) { - // 从令牌中获取用户信息 - Long userId = JwtUtils.getUserIdFromToken(token); - - // 构建Redis key:tacit:user:token:{userId} - String redisKey = CommonConstant.REDIS_KEY_TACIT_USER_TOKEN + userId; - - // 验证Redis中的令牌是否存在且匹配 - String redisToken = redisUtils.get(redisKey); - if (token.equals(redisToken)) { - String username = JwtUtils.getUsernameFromToken(token); - String role = JwtUtils.getRoleFromToken(token); - - // 创建认证对象 - User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); - var authentication = new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } - } catch (Exception e) { - log.error("JWT令牌验证失败: {}", e.getMessage()); - } - } else { - // 检查是否有用户上下文头(网关转发或服务间调用时添加) - String userId = request.getHeader("X-User-Id"); - String username = request.getHeader("X-Username"); - String role = request.getHeader("X-Role"); + // 只从请求头中获取用户信息,不做鉴权 + String userIdStr = request.getHeader("X-User-Id"); + String username = request.getHeader("X-Username"); + String role = request.getHeader("X-Role"); - if (userId != null && username != null && role != null) { - User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); - var authentication = new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - } + if (userIdStr != null && username != null && role != null) { + User principal = new User(username, "", Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))); + var authentication = new org.springframework.security.authentication.UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities()); + + // 创建用户详情map,存储userId等信息 + HashMap userDetails = new HashMap<>(); + userDetails.put("userId", Long.parseLong(userIdStr)); + userDetails.put("username", username); + userDetails.put("role", role); + authentication.setDetails(userDetails); + + SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); diff --git a/tacit-app-api/src/main/java/com/tacit/app/service/impl/UserServiceImpl.java b/tacit-app-api/src/main/java/com/tacit/app/service/impl/UserServiceImpl.java index 4723129..85eb5ec 100644 --- a/tacit-app-api/src/main/java/com/tacit/app/service/impl/UserServiceImpl.java +++ b/tacit-app-api/src/main/java/com/tacit/app/service/impl/UserServiceImpl.java @@ -10,6 +10,7 @@ import com.tacit.app.service.UserService; import com.tacit.common.constant.CommonConstant; import com.tacit.common.exception.BusinessException; import com.tacit.common.utils.JwtUtils; +import com.tacit.common.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.security.crypto.password.PasswordEncoder; @@ -91,6 +92,8 @@ public class UserServiceImpl extends ServiceImpl implements Us @Override public User getUserInfo(Long userId) { + Long currentUserId = SecurityUtils.getCurrentUserId(); + System.out.println("currentUserId: " + currentUserId); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id", userId) .eq("del_flag", 0);