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

React+Go应用集成Active Directory无缝单点登录(SSSO)实现求助

实现AD无缝SSO的解决方案(React+Go)

在你的技术栈和AD环境下,Kerberos + SPNEGO是实现无缝SSO的最佳选择——AD原生支持Kerberos,能实现用户已登录域时完全无感知的自动认证,比NTLM安全,比SAML轻量化(无需跳转身份提供商页面)。下面是具体实现步骤:

一、方案选型说明

  • 排除SAML:适合跨域多系统场景,配置复杂且需要跳转身份提供商页面,不符合“无缝”需求。
  • 排除NTLM:旧协议,安全性低于Kerberos,且易触发浏览器认证弹窗,无法真正无缝。
  • 选择Kerberos+SPNEGO:AD原生支持,SPNEGO让浏览器自动与后端协商Kerberos认证,域内已登录用户无感知进入应用。

二、Go后端实现

1. 注册服务主体名称(SPN)

在AD中为Go服务注册SPN,这是Kerberos认证的核心前提:

  • 打开AD用户和计算机,创建或选择运行Go服务的专用域账户(避免用普通用户账户)。
  • 在域控制器或已加入域的机器上执行命令:
    setspn -A HTTP/your-app-domain:port domain\service-account
    
    示例:若应用域名为app.corp.com,端口8080,服务账户为corp\app-svc,则命令为:
    setspn -A HTTP/app.corp.com:8080 corp\app-svc
    
  • 验证SPN注册结果:setspn -L corp\app-svc

2. 生成服务账户Keytab文件

Keytab用于Go服务无需输入密码即可验证Kerberos令牌,生成命令:

ktpass /out app-svc.keytab /princ HTTP/app.corp.com:8080@CORP.COM /mapuser corp\app-svc /pass * /ptype KRB5_NT_PRINCIPAL

执行后输入服务账户密码,生成的app-svc.keytab文件需放到Go服务可访问的路径下。

3. 集成SPNEGO认证中间件

使用gokrb5库实现SPNEGO认证中间件,整合到现有Go后端:

import (
	"net/http"
	"strings"
	"github.com/jcmturner/gokrb5/v8/config"
	"github.com/jcmturner/gokrb5/v8/spnego"
)

// SSOAuthMiddleware 处理Kerberos/SPNEGO认证
func SSOAuthMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		authHeader := r.Header.Get("Authorization")
		// 未携带认证头,触发浏览器Kerberos认证流程
		if authHeader == "" || !strings.HasPrefix(authHeader, "Negotiate ") {
			w.Header().Set("WWW-Authenticate", "Negotiate")
			w.WriteHeader(http.StatusUnauthorized)
			return
		}

		// 加载Kerberos配置(可从域控制器获取krb5.conf,或手动配置)
		krb5Conf, err := config.Load("./krb5.conf")
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// 初始化SPNEGO客户端,使用服务账户的Keytab
		spnegoClient, err := spnego.NewClientWithKeytab(
			"HTTP/app.corp.com:8080",
			"CORP.COM",
			"./app-svc.keytab",
			krb5Conf,
		)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// 验证客户端发送的Kerberos令牌
		token := strings.TrimPrefix(authHeader, "Negotiate ")
		authResult, err := spnegoClient.AcceptSecurityContext([]byte(token))
		if err != nil {
			w.Header().Set("WWW-Authenticate", "Negotiate")
			w.WriteHeader(http.StatusUnauthorized)
			return
		}

		// 认证成功,获取用户主体名称,传递给后续处理逻辑
		r.Header.Set("X-AD-User-Principal", authResult.UserName())
		next.ServeHTTP(w, r)
	})
}
  • 认证成功后,可通过用户主体名称(authResult.UserName())调用现有LDAP逻辑,获取用户详细信息并创建会话。

三、React前端配合

  • 前端只需在应用初始化时发起一个SSO验证请求(比如GET /api/sso/check):
    • 若请求返回200,说明用户已通过Kerberos认证,直接进入应用主页。
    • 若请求返回401,说明用户未登录AD或认证失败,跳转至现有LDAP登录页面。
  • 浏览器配置:需将应用域名加入浏览器的信任列表,比如:
    • Edge/IE:添加到“本地Intranet”区域。
    • Chrome:启动时添加参数--auth-server-whitelist="app.corp.com",确保浏览器自动发送Kerberos令牌。

四、关键注意事项

  • Go服务若运行在非域机器上,必须使用Keytab文件;若在域机器上,可直接使用服务账户的域身份。
  • 客户端机器必须加入AD域,且用户已登录域账户。
  • 确保SPN注册无重复,否则会导致Kerberos认证失败(可使用setspn -X检查重复)。
  • 防火墙需开放Kerberos默认端口(88/UDP、88/TCP)。

内容的提问来源于stack exchange,提问作者razork

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:05:28