强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Git 服务器搭建完全指南 / 第 11 章 - 认证集成

第 11 章 - 认证集成

企业环境中,Git 服务器需要与现有的身份认证系统集成,实现统一登录(SSO)和集中用户管理。

11.1 认证方案概览

方案适用场景复杂度GiteaGitLab
LDAP/AD企业内部有 AD/LDAP
OAuth2使用第三方 IdP
SAML企业 SSO(如 Okta)✅ (EE)
OpenID Connect现代 Web SSO
CAS高校/传统企业
SMTP邮件账号登录

11.2 LDAP 集成

11.2.1 LDAP 基础概念

LDAP 目录树结构:

dc=example,dc=com (根)
├── ou=people (用户)
│   ├── uid=alice
│   ├── uid=bob
│   └── uid=charlie
├── ou=groups (组)
│   ├── cn=developers
│   ├── cn=admins
│   └── cn=ops
└── ou=service (服务账号)
    └── cn=git-bind

11.2.2 Gitea LDAP 配置

Web 界面配置

  1. 登录管理后台 → AdministrationAuthentication
  2. 点击 Add Authentication Source
  3. 选择 LDAP (via BindDN)LDAP (simple auth)

API 配置

# 添加 LDAP 认证源
curl -s -X POST -H "Authorization: token $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITEA_URL/api/v1/admin/auths" \
  -d '{
    "type": "LDAP",
    "name": "公司 LDAP",
    "host": "ldap.example.com",
    "port": 389,
    "security_protocol": "StartTLS",
    "bind_dn": "cn=git-bind,ou=service,dc=example,dc=com",
    "bind_password": "ldap_bind_password",
    "user_search_base": "ou=people,dc=example,dc=com",
    "user_filter": "(&(objectClass=posixAccount)(uid=%s))",
    "admin_filter": "(memberOf=cn=admins,ou=groups,dc=example,dc=com",
    "username_attribute": "uid",
    "first_name_attribute": "givenName",
    "surname_attribute": "sn",
    "email_attribute": "mail",
    "public_ssh_key_attribute": "sshPublicKey",
    "groups_attribute": "memberOf",
    "group_filter": "",
    "group_dn": "",
    "group_membership_uid": "",
    "skip_local_2fa": false,
    "is_sync_enabled": true,
    "is_active": true
  }'

11.2.3 LDAP 配置参数说明

参数说明示例
HostLDAP 服务器地址ldap.example.com
PortLDAP 端口389 (LDAP), 636 (LDAPS)
Bind DN服务账号 DNcn=git-bind,ou=service,dc=example,dc=com
Bind Password服务账号密码(安全存储)
User Search Base用户搜索基线ou=people,dc=example,dc=com
User Filter用户过滤器(&(objectClass=posixAccount)(uid=%s))
Admin Filter管理员过滤器(memberOf=cn=admins,…)
Username Attribute用户名属性uid / sAMAccountName
Email Attribute邮箱属性mail

11.2.4 常用 LDAP 过滤器

# Active Directory 用户
(&(objectCategory=Person)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))

# OpenLDAP 用户
(&(objectClass=posixAccount)(uid=%s))

# 仅活跃用户
(&(objectClass=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(uid=%s))

# 管理员组成员
(memberOf=cn=git-admins,ou=groups,dc=example,dc=com)

# 多组成员(OR)
(|(memberOf=cn=devs,...)(memberOf=cn=ops,...))

11.2.5 GitLab LDAP 配置

# /etc/gitlab/gitlab.rb

gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = {
  'main' => {
    'label' => '公司 LDAP',
    'host' => 'ldap.example.com',
    'port' => 389,
    'uid' => 'sAMAccountName',
    'encryption' => 'start_tls',
    'bind_dn' => 'CN=git-bind,OU=Service,DC=example,DC=com',
    'password' => 'ldap_bind_password',
    'active_directory' => true,
    'base' => 'OU=People,DC=example,DC=com',
    'verify_certificates' => true,
    'allow_username_or_email_login' => true,
    'block_auto_created_users' => false,
    'group_base' => 'OU=Groups,DC=example,DC=com',
    'admin_group' => 'git-admins',
    'sync_ssh_keys' => 'sshPublicKey',
    
    # 属性映射
    'attributes' => {
      'username' => ['sAMAccountName', 'uid'],
      'email' => ['mail', 'email'],
      'name' => 'displayName',
      'first_name' => 'givenName',
      'last_name' => 'sn'
    }
  }
}
# 应用配置
sudo gitlab-ctl reconfigure

# 测试 LDAP 连接
sudo gitlab-rake gitlab:ldap:check

# 同步 LDAP 用户
sudo gitlab-rake gitlab:ldap:sync

11.2.6 LDAP 用户同步

#!/bin/bash
# ldap-sync.sh - 定期同步 LDAP 用户

GITEA_URL="https://git.example.com"
ADMIN_TOKEN="your_admin_token"

# 触发 LDAP 同步
curl -s -X POST -H "Authorization: token $ADMIN_TOKEN" \
  "$GITEA_URL/api/v1/admin/user/repo_migrate" || true

# 使用 ldapsearch 验证连接
ldapsearch -x -H ldap://ldap.example.com \
  -D "cn=git-bind,ou=service,dc=example,dc=com" \
  -w "bind_password" \
  -b "ou=people,dc=example,dc=com" \
  "(objectClass=posixAccount)" uid mail

echo "LDAP 同步完成: $(date)"

11.2.7 LDAP 调试

# 测试 LDAP 连接
ldapsearch -x -H ldap://ldap.example.com \
  -D "cn=git-bind,ou=service,dc=example,dc=com" \
  -w "bind_password" \
  -b "ou=people,dc=example,dc=com" \
  "(&(objectClass=posixAccount)(uid=alice))"

# 使用 LDAPS
ldapsearch -x -H ldaps://ldap.example.com:636 \
  -D "cn=git-bind,ou=service,dc=example,dc=com" \
  -w "bind_password" \
  -b "ou=people,dc=example,dc=com" \
  -ZZ \
  "(uid=alice)"

# 测试 Gitea LDAP 认证
curl -s -X POST "$GITEA_URL/api/v1/users/alianame/tokens" \
  -u "alianame:ldap_password"

11.3 OAuth2 集成

11.3.1 OAuth2 流程

用户浏览器          Gitea/Forgejo            OAuth2 Provider
     │                    │                        │
     │── 点击登录 ──────►│                        │
     │                    │── 重定向 ─────────────►│
     │◄─── 登录页面 ──────│◄──────────────────────│
     │                    │                        │
     │── 输入凭据 ──────────────────────────────►│
     │◄── 授权码 ───────────────────────────────│
     │                    │                        │
     │── 回调带授权码 ──►│                        │
     │                    │── 用授权码换 Token ───►│
     │                    │◄── Access Token ─────│
     │                    │                        │
     │                    │── 获取用户信息 ───────►│
     │                    │◄── 用户资料 ─────────│
     │                    │                        │
     │◄── 登录成功 ──────│                        │

11.3.2 Gitea OAuth2 配置

支持的 OAuth2 Provider

Provider类型说明
GitHubOAuth2使用 GitHub 账号登录
GitLabOAuth2使用 GitLab.com 账号登录
GoogleOAuth2Google Workspace
KeycloakOpenID Connect自托管 IdP
自定义OAuth2/OIDC任意 OAuth2 兼容服务

配置 Keycloak OAuth2

# 添加 OAuth2 认证源
curl -s -X POST -H "Authorization: token $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  "$GITEA_URL/api/v1/admin/auths" \
  -d '{
    "type": "OAuth2",
    "name": "Keycloak",
    "provider": "openidConnect",
    "client_id": "gitea-client",
    "client_secret": "your-client-secret",
    "auto_discover_url": "https://keycloak.example.com/realms/master/.well-known/openid-configuration",
    "icon_url": "https://keycloak.example.com/icon.png",
    "required_claim_name": "",
    "required_claim_value": "",
    "group_claim_name": "groups",
    "admin_group": "gitea-admins",
    "skip_local_2fa": true,
    "is_auto_discover": true,
    "allow_deactivate_2fa": false,
    "is_sync_enabled": true,
    "is_active": true
  }'

11.3.3 GitLab OAuth2 配置

# /etc/gitlab/gitlab.rb

# Keycloak (OpenID Connect)
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_providers'] = [
  {
    name: 'openid_connect',
    label: 'Keycloak SSO',
    args: {
      name: 'openid_connect',
      scope: ['openid', 'profile', 'email'],
      response_type: 'code',
      issuer: 'https://keycloak.example.com/realms/master',
      discovery: true,
      client_auth_method: 'query',
      uid_field: 'preferred_username',
      send_scope_to_token_endpoint: 'true',
      client_options: {
        identifier: 'gitlab-client',
        secret: 'your-client-secret',
        redirect_uri: 'https://git.example.com/users/auth/openid_connect/callback'
      }
    }
  }
]

# GitHub OAuth
gitlab_rails['omniauth_providers'] = [
  {
    name: 'github',
    label: 'GitHub',
    app_id: 'your-github-client-id',
    app_secret: 'your-github-client-secret',
    args: { scope: 'user:email' }
  }
]
sudo gitlab-ctl reconfigure

11.4 SAML 集成

11.4.1 SAML 工作原理

用户              Gitea/GitLab            IdP (如 Okta, ADFS)
 │                    │                         │
 │── 访问 Git ──────►│                         │
 │                    │── SAMLRequest ─────────►│
 │◄── 重定向到 IdP ──│◄──────────────────────│
 │                    │                         │
 │── 登录 IdP ──────────────────────────────►│
 │◄── SAMLResponse ─────────────────────────│
 │                    │                         │
 │── 提交 Response ─►│                         │
 │                    │── 验证签名和属性 ──────│
 │                    │                         │
 │◄── 登录成功 ──────│                         │

11.4.2 Gitea SAML 配置

Gitea 原生支持 SAML(需要通过 OAuth2/OIDC 桥接或直接配置)。

通常推荐的方案是通过 Keycloak 同时支持 SAML 和 OIDC:

  1. 在 Keycloak 中创建 SAML Client
  2. Gitea 通过 OpenID Connect 连接到 Keycloak
  3. Keycloak 在后端通过 SAML 与企业 IdP 联合认证

11.5 Keycloak 统一身份管理

11.5.1 Keycloak 安装

# docker-compose.yml
version: '3'

services:
  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    container_name: keycloak
    restart: always
    environment:
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin_password
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://keycloak-db:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: keycloak_password
      KC_HOSTNAME: keycloak.example.com
      KC_HTTP_RELATIVE_PATH: /auth
    ports:
      - "8080:8080"
      - "8443:8443"
    command: start-dev
    depends_on:
      - keycloak-db

  keycloak-db:
    image: postgres:16-alpine
    container_name: keycloak-db
    restart: always
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: keycloak_password
    volumes:
      - keycloak-data:/var/lib/postgresql/data

volumes:
  keycloak-data:

11.5.2 配置 Gitea 客户端

在 Keycloak 管理界面:

  1. 创建 Realm(如 git
  2. 创建 Client:
    • Client ID: gitea
    • Client Protocol: openid-connect
    • Root URL: https://git.example.com
    • Valid Redirect URIs: https://git.example.com/user/oauth2/keycloak/callback
  3. 创建 Client Secret
  4. 配置 Mappers:
    • preferred_username → 用户名
    • email → 邮箱
    • groups → 组(用于 GitLab group sync)

11.6 SSH 密钥管理

11.6.1 LDAP 同步 SSH 密钥

如果 LDAP 中存储了 SSH 公钥(如 sshPublicKey 属性),Gitea 可以自动同步:

# 确认 LDAP 配置中设置了 sshPublicKey
# Gitea → Administration → Authentication → LDAP
# SSH Public Key Attribute: sshPublicKey

# 手动触发同步
# Gitea → Site Administration → User Accounts → 同步用户

11.6.2 SSH 证书认证

企业级环境推荐使用 SSH 证书代替个人密钥:

# 在 CA 服务器上签发用户证书
ssh-keygen -s ca_key -I "[email protected]" \
  -n alice \
  -V +52w \
  alice_key.pub

# 生成 alice_key-cert.pub
# 配置 SSH 服务器信任 CA
echo "@cert-authority *.example.com $(cat ca_key.pub)" >> /etc/ssh/ssh_known_hosts

11.7 双因素认证(2FA)

11.7.1 启用 2FA

Gitea

# 强制所有用户启用 2FA(管理后台配置)
# Administration → Authentication → 强制 2FA

# 或通过配置文件
# [security]
# TWO_FACTOR_AUTH = true

GitLab

# /etc/gitlab/gitlab.rb
gitlab_rails['require_two_factor_authentication'] = true
gitlab_rails['two_factor_grace_period'] = 24  # 24 小时宽限期

11.7.2 2FA 与 SSH/Token

启用 2FA 后:

  • SSH 密钥认证不受影响(推荐方式)
  • HTTPS 认证需要使用 Personal Access Token 或 OAuth Token 代替密码
  • Git Credential Manager 可以安全存储 Token

11.8 扩展阅读


本章小结

学到了什么关键要点
LDAP最常见的企业认证方式,支持 AD 和 OpenLDAP
OAuth2适合第三方 IdP(Keycloak、GitHub、Google)
SAML企业 SSO 标准,推荐通过 Keycloak 桥接
2FA启用后需使用 Token 代替密码(SSH 不受影响)
Keycloak统一身份管理平台,支持 LDAP/OIDC/SAML 联合

下一章:第 12 章 - 仓库迁移 — 从 GitHub/GitLab 迁移仓库和历史清理。