Codex Assistant
昨天 afeeed281e60466b576fbe74d339634cc5d07b82
backend/src/main/java/com/rongyichuang/auth/filter/JwtAuthenticationFilter.java
@@ -134,18 +134,12 @@
                ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
                byte[] content = wrapper.getContentAsByteArray();
                if (content.length > 0) {
                    return new String(content, wrapper.getCharacterEncoding());
                    String encoding = wrapper.getCharacterEncoding() != null ? wrapper.getCharacterEncoding() : "UTF-8";
                    return new String(content, encoding);
                }
            }
            // 如果不是包装器,尝试直接读取(可能会消耗请求体)
            StringBuilder buffer = new StringBuilder();
            String line;
            java.io.BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            return buffer.toString();
            // 不从原始请求流读取,避免下游组件拿不到请求体导致 400
            return null;
        } catch (Exception e) {
            logger.warn("读取请求体失败", e);
            return null;
@@ -215,27 +209,30 @@
            // 先检查Authorization头,如果没有token,再检查是否为公开查询
            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                logger.debug("GraphQL请求没有Authorization头,检查是否为公开查询");
                logger.debug("GraphQL请求没有Authorization头,尝试判定是否为公开查询");
                
                // 检查是否为公开查询
                // 尝试判定公开查询;如果能确定是公开查询则放行
                if (isPublicGraphQLQuery(wrappedRequest)) {
                    logger.debug("检测到公开GraphQL查询,允许匿名访问");
                    // 设置匿名认证,让Spring Security知道这是一个已认证的匿名用户
                    AnonymousAuthenticationToken anonymousAuth = new AnonymousAuthenticationToken(
                        "anonymous",
                        "anonymous",
                        "anonymous",
                        "anonymous",
                        Arrays.asList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))
                    );
                    SecurityContextHolder.getContext().setAuthentication(anonymousAuth);
                    logger.debug("为公开GraphQL查询设置匿名认证");
                    filterChain.doFilter(wrappedRequest, response);
                    return;
                }
                
                logger.warn("GraphQL请求缺少有效的Authorization头且不是公开查询");
                sendUnauthorizedResponse(response);
                // 无法可靠读取/判定请求体时,默认以匿名身份放行到GraphQL层,由各Resolver自行进行权限校验
                logger.debug("无法可靠判定是否为公开查询,设置匿名认证并交由GraphQL层处理");
                AnonymousAuthenticationToken anonymousAuth = new AnonymousAuthenticationToken(
                    "anonymous",
                    "anonymous",
                    Arrays.asList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))
                );
                SecurityContextHolder.getContext().setAuthentication(anonymousAuth);
                filterChain.doFilter(wrappedRequest, response);
                return;
            }
            
@@ -250,23 +247,37 @@
                    return;
                }
                
                // 查找用户信息并设置认证
                Optional<User> userOpt = userRepository.findById(userId);
                if (userOpt.isPresent()) {
                    User user = userOpt.get();
                // 检查是否为匿名用户(负数用户ID)
                if (userId < 0) {
                    // 匿名用户,设置特殊的认证信息
                    UsernamePasswordAuthenticationToken authToken = 
                        new UsernamePasswordAuthenticationToken(
                            user.getId().toString(),
                            "anonymous_" + userId,
                            null, 
                            new ArrayList<>()
                            Arrays.asList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))
                        );
                    authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authToken);
                    logger.debug("GraphQL请求认证成功: userId={}", user.getId());
                    logger.debug("GraphQL请求匿名用户认证成功: userId={}", userId);
                } else {
                    logger.warn("GraphQL请求的用户不存在: userId={}", userId);
                    sendUnauthorizedResponse(response);
                    return;
                    // 正常用户,查找用户信息并设置认证
                    Optional<User> userOpt = userRepository.findById(userId);
                    if (userOpt.isPresent()) {
                        User user = userOpt.get();
                        UsernamePasswordAuthenticationToken authToken =
                            new UsernamePasswordAuthenticationToken(
                                user.getId().toString(),
                                null,
                                new ArrayList<>()
                            );
                        authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authToken);
                        logger.debug("GraphQL请求认证成功: userId={}", user.getId());
                    } else {
                        logger.warn("GraphQL请求的用户不存在: userId={}", userId);
                        sendUnauthorizedResponse(response);
                        return;
                    }
                }
            } catch (Exception e) {
                logger.error("GraphQL请求JWT验证失败: {}", e.getMessage());
@@ -309,26 +320,40 @@
            if (jwtUtil.validateToken(token)) {
                logger.debug("Token验证成功,查找用户信息");
                
                // 查找用户信息
                Optional<User> userOpt = userRepository.findById(userId);
                if (userOpt.isPresent()) {
                    User user = userOpt.get();
                    logger.debug("找到用户: userId={}, phone={}", user.getId(), user.getPhone());
                    // 创建认证对象
                // 检查是否为匿名用户(负数用户ID)
                if (userId < 0) {
                    // 匿名用户,设置特殊的认证信息
                    UsernamePasswordAuthenticationToken authToken = 
                        new UsernamePasswordAuthenticationToken(
                            user.getId().toString(),
                            "anonymous_" + userId,
                            null, 
                            new ArrayList<>() // 暂时不设置权限,后续可以根据角色设置
                            Arrays.asList(new SimpleGrantedAuthority("ROLE_ANONYMOUS"))
                        );
                    authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authToken);
                    logger.info("用户认证成功: userId={}, phone={}", user.getId(), user.getPhone());
                    logger.info("匿名用户认证成功: userId={}", userId);
                } else {
                    logger.warn("用户不存在: userId={}", userId);
                    // 正常用户,查找用户信息
                    Optional<User> userOpt = userRepository.findById(userId);
                    if (userOpt.isPresent()) {
                        User user = userOpt.get();
                        logger.debug("找到用户: userId={}, phone={}", user.getId(), user.getPhone());
                        // 创建认证对象
                        UsernamePasswordAuthenticationToken authToken =
                            new UsernamePasswordAuthenticationToken(
                                user.getId().toString(),
                                null,
                                new ArrayList<>() // 暂时不设置权限,后续可以根据角色设置
                            );
                        authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authToken);
                        logger.info("用户认证成功: userId={}, phone={}", user.getId(), user.getPhone());
                    } else {
                        logger.warn("用户不存在: userId={}", userId);
                    }
                }
            } else {
                logger.warn("Token验证失败");