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

如何在Django中实现多提供商OpenID Connect单点登录

Django 动态多租户 OpenID Connect SSO 实现方案

不需要强依赖那些已废弃、或者绑定死静态配置/本地认证逻辑的第三方库,直接基于OIDC标准协议实现核心流程即可,灵活度最高,后续新增身份提供商也方便。

第一步:搭建动态SSO配置存储模型

专门建一张数据库表存储所有企业客户自主配置的SSO连接参数,完全脱离settings.py静态配置限制:

  • 关联字段:绑定配置所属的企业租户,标记配置归属
  • 核心OIDC参数字段:client_id、client_secret(必须做字段级加密存储,禁止明文落库)、授权端点、令牌端点、用户信息端点、签发方标识,默认授权范围固定填openid email profile即可
  • 身份提供商类型字段:预置Azure、Okta两个选项,后续新增其他IdP直接追加选项就行;用户选择对应类型时可以自动填充对应IdP的标准端点模板,比如Azure自动填充https://login.microsoftonline.com/{租户ID}/v2.0/路径下的各端点,减少客户手动输入成本
  • 状态控制字段:标记配置是否启用,支持客户在后台测试连通性后再正式上线

第二步:落地目标登录流程

完全匹配需要的交互逻辑:

  • 登录页加载时,从配置表拉取所有已启用的企业SSO配置,为每个企业生成专属登录按钮,按钮携带对应配置的唯一ID参数
  • 用户点击对应企业的SSO按钮后,后端根据配置ID查库拿到对应IdP的全量参数,动态生成授权跳转请求:
    • 生成随机state参数存在当前用户session中,回调时做CSRF校验
    • 回调地址拼接当前配置的唯一标识,方便回调环节快速定位对应配置
    • 针对不同IdP的特殊参数要求做适配,比如Azure默认带prompt=select_account参数,这部分逻辑按IdP类型拆分即可,不耦合核心流程
  • 处理IdP回调请求:
    • 首先校验回调携带的state参数和session中存储的是否一致,不一致直接拦截请求
    • 拿回调返回的授权码,搭配库中存储的client_id、client_secret请求对应IdP的令牌端点,换取访问令牌
    • 用访问令牌请求用户信息端点,拉取用户姓名、邮箱字段;这里加一层字段映射适配,兼容不同IdP返回的字段名差异,比如Azure返回姓名字段为name,Okta可能同时返回name和preferred_username,统一映射成标准的姓名、邮箱字段即可
  • 完成本地登录:拿到用户邮箱后直接查询本地用户表匹配已有账号,匹配成功直接调用Django原生的login()函数写入会话完成登录,不需要绑定第三方库的认证后端;如果匹配不到账号,可以按业务规则走引导流程,比如提示联系企业管理员开通,或者按规则自动创建账号。

第三步:做可扩展设计,适配后续新增IdP

把不同IdP的差异逻辑拆成独立适配类,基类统一约定三个核心方法:生成授权地址、兑换令牌、解析用户信息。后续新增身份提供商时,只需要继承基类实现对应差异逻辑,注册到IdP类型映射表即可,不需要改动核心登录流程代码。

关键安全注意点

  • 数据库中存储的所有client_secret必须做字段级加密,用Django配套的加密组件实现即可,禁止明文存储
  • 回调环节严格校验跳转地址,防止开放重定向漏洞
  • 拿到IdP返回的令牌后,必须校验iss(签发方)、aud(受众,即对应的client_id)字段合法性,防止伪造令牌绕过登录
  • 管理后台给客户提供配置测试功能,保存配置时自动模拟走一遍授权流程,提前提示参数错误,减少线上登录故障

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:33:16