You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Next.js+Next-Auth中的HTTP 431错误及图片渲染问题

问题:JWT携带用户照片触发HTTP 431错误,无法渲染用户头像

技术栈:Next.js、TypeScript、Next-Auth、Keycloak、LDAP
用户照片从LDAP同步到Keycloak,应用通过Next-Auth认证后将用户信息存入JWT Token。但当存在照片的用户登录时,应用触发HTTP 431 Request Header Fields Too Large错误,导致用户照片无法渲染。


Next-Auth配置代码

import { get, maxHeaderSize } from "http";
import { NextAuthOptions } from "next-auth"
import KeycloakProvider from "next-auth/providers/keycloak";
import { setGlobal } from "next/dist/trace";

export const authOptions: NextAuthOptions = {
  providers: [
    KeycloakProvider({
      clientId: process.env.KC_CLIENT_ID,
      clientSecret: process.env.KC_CLIENT_SECRET,
      issuer: process.env.KC_ISSUER,
    })
  ],
  callbacks: {
    // Servidor
    jwt: async ({ token, user, profile }) => {
      const customUser = profile as unknown as any

      console.log(setGlobal(maxHeaderSize, 1000))
      if (user) {
        return {
          ...token,
          newemail: customUser.mailPrimaryAddress,
          company: customUser.company,
          group: customUser.group,
          jpegPhoto: customUser.jpegPhoto
        }
      }
      return token
    },
    // Cliente
    session: async ({ session, token }) => {
      return {

        ...session,
        user: {
          name: token.name,
          email: token.email,
          // 注释的自定义字段
          // company: token.company,
          // group: token.group,
          // jpegPhoto: token.jpegPhoto,
        }
      }
    },
  },
  events: {
    async signOut() {
      await get(ENV)
    }
  }
}

Middleware代码

import { NextAuthMiddlewareOptions, NextRequestWithAuth, withAuth } from "next-auth/middleware"
import { NextResponse } from "next/server"

const middleware = (request:NextRequestWithAuth) =>{
  console.log("[MIDDLEWARE_NEXTAUTH_TOKEN]: ", request.nextauth.token)

  const isPrivateRoutes = request.nextUrl.pathname.startsWith("/private/admin")
  const isAdminUser = request.nextauth.token?.group === 'admin'

  if(isPrivateRoutes && !isAdminUser){
    return NextResponse.rewrite(new URL('/denied', request.url))
  }
}
const callbackOptions:NextAuthMiddlewareOptions = {}

export default withAuth(middleware,callbackOptions)
export const config ={
  matcher: ['/private/:path*']
};

图片渲染组件代码

'use client'
import { useSession } from "next-auth/react"
import Image from "next/image"

const ClientImage = () => {
  const session = useSession()

  const imgUrl = session.data?.user["jpegPhoto"]
  return (
    <div>
      {/* {session && <Image src={imgUrl} alt="imagem do usuario" />} */}
      {session && <pre>{JSON.stringify(session, null, 1)}</pre>}
    </div>
  )
}

export { ClientImage }

问题分析与解决建议

HTTP 431错误核心原因是请求头过大:用户照片(jpegPhoto)是Base64编码的二进制数据,直接存入JWT会大幅增加Token体积,导致Cookie或Authorization头超出服务器允许的大小限制。

具体优化方案

  1. 避免将照片二进制数据存入JWT

    • 从Keycloak获取用户照片的URL而非Base64数据:在Keycloak中配置用户属性时,存储照片的访问地址(比如Keycloak提供的用户头像API端点),而非直接存Base64编码。
    • 修改Next-Auth的jwt回调,只存入照片URL:
      jwt: async ({ token, user, profile }) => {
        const customUser = profile as unknown as any
        if (user) {
          return {
            ...token,
            newemail: customUser.mailPrimaryAddress,
            company: customUser.company,
            group: customUser.group,
            jpegPhotoUrl: customUser.jpegPhotoUrl // 替换为照片URL
          }
        }
        return token
      }
      
  2. 调整服务器请求头大小限制(临时方案)

    • 若必须使用Base64数据,需增大Next.js和Keycloak的请求头限制:
      • Next.js:在next.config.js中配置或修改Node.js的maxHeaderSize参数(当前代码中setGlobal(maxHeaderSize, 1000)设置过小,建议设为1048576即1MB);
      • Keycloak:修改standalone.xml或domain.xml中的http-listener配置,增大max-header-size属性。
  3. 优化Session回调与客户端渲染

    • 在session回调中返回照片相关字段,确保客户端useSession能获取到:
      session: async ({ session, token }) => {
        return {
          ...session,
          user: {
            name: token.name,
            email: token.email,
            company: token.company,
            group: token.group,
            jpegPhotoUrl: token.jpegPhotoUrl // 或保留jpegPhoto(若用URL)
          }
        }
      }
      
    • 客户端渲染时,若用Base64需补全前缀data:image/jpeg;base64,,若用URL直接传入Image组件即可。
  4. 改用服务器端获取照片

    • 创建API路由(如/api/user/photo),在服务器端通过JWT中的用户ID从Keycloak/LDAP获取照片并返回二进制数据,客户端直接请求该API获取照片,避免在JWT中携带大体积数据。

内容的提问来源于stack exchange,提问作者Samuel Máximo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:13:19