当前位置: 首页 > news >正文

OA ⇄ CRM 单点登录(SSO)实现说明

本文档说明在本仓库中基于自研认证体系(未使用 Django 默认认证)实现 OA → CRM 单点登录的整体方案、修改点、接口规范、配置方式、验证方法与安全要点。### 一、实现目标
- 在 OA 系统成功登录后,点击“进入CRM系统”即可自动登录 CRM,无需再次输入用户名密码。
- 兼容现有自定义会话结构与中间件,不改动既有业务登录逻辑。### 二、整体架构与流程
1. 用户在 OA 登录(`/login/`)成功,OA 设置自己的会话 `request.session["app"]`。
2. 用户点击 OA 导航中的“进入CRM系统”:访问 OA 的 `/crm/sso/redirect/`。
3. OA 从自己的会话中取出用户名,拼装参数 `username|ts|nonce`,使用共享密钥 `SSO_SHARED_SECRET` 生成签名 `sig`,并重定向到 CRM 的 `/oa/sso/login/`。
4. CRM 校验签名、时间窗口等,通过后在 CRM 端创建与自研体系一致的会话 `request.session["app"]` 并登录,随后跳转到目标页面。### 三、关键代码位置1) OA 侧
- 跳转视图:`oa/app/view/account.py` → `crm_sso_redirect`
- URL:`oa/oa/urls.py` 添加 `path('crm/sso/redirect/', account.crm_sso_redirect, name='crm_sso_redirect')`
- 导航入口:`oa/app/templates/layout.html` 导航栏加入“进入CRM系统”按钮,指向 `/crm/sso/redirect/?next=/index/`
- 中间件白名单:`oa/app/middleware/auth.py` 允许匿名访问 `/crm/sso/redirect/`
- 配置:`oa/oa/settings.py` 新增 `CRM_BASE_URL` 和共用的 `SSO_SHARED_SECRET`2) CRM 侧
- SSO 登录视图:`app/view/account.py` → `oa_sso_login`
- 辅助接口:`sso_status_api`(查看登录态)、`sso_debug`(生成调试链接)
- URL:`CRM/urls.py` 已包含以下路由- `path('oa/sso/login/', account.oa_sso_login)`- `path('sso/status/', account.sso_status_api)`- `path('sso/debug/', account.sso_debug)`
- 中间件白名单:`app/midieware/auth.py` 放行上述 3 个路径
- 配置:`CRM/settings.py` 包含同一份 `SSO_SHARED_SECRET`### 四、接口与签名规范1) OA → CRM 重定向
- 目标:`{CRM_BASE_URL}/oa/sso/login/`
- Query 参数:- `username`:OA 当前用户在 CRM 中的用户名- `ts`:时间戳(秒)- `nonce`:随机字符串(防重放)- `sig`:签名- `next`:登录后跳转页面(可选,默认 `/index/`)2) 签名规则
- 拼串:`payload = f"{username}|{ts}|{nonce}"`
- `sig = HMAC_SHA256(SSO_SHARED_SECRET, payload)`,以 16 进制字符串输出
- 时间窗口:±120 秒(超时拒绝)
- 校验:CRM 使用相同密钥与规则计算,对比 `sig`,并检查时间窗口3) CRM 登录逻辑
- 通过签名与时间窗口后,CRM 检索 `models.Admin.objects.filter(username=username).first()`
- 校验用户是否存在/是否被禁用
- 构造 CRM 自定义会话:```pythonrequest.session["app"] = {'id': admin_obj.id,'name': admin_obj.name,'username': admin_obj.username,'role': admin_obj.role,}request.session.set_expiry(60*60*24*7)```### 五、配置项1) 双端共享密钥(必须一致)
- `oa/oa/settings.py`:```pythonSSO_SHARED_SECRET = '123abc!@#'  # 请在生产替换并保密```
- `CRM/settings.py`:```pythonSSO_SHARED_SECRET = '123abc!@#'```2) 服务地址
- OA 访问地址:`127.0.0.1:8018`
- CRM 访问地址:`127.0.0.1:8009`
- OA 中 CRM 基地址:`oa/oa/settings.py````pythonCRM_BASE_URL = 'http://127.0.0.1:8009'```3) Cookie 隔离
- OA:`oa/oa/settings.py` → `SESSION_COOKIE_NAME = 'oa_sessionid'`
- CRM:`CRM/settings.py` → `SESSION_COOKIE_NAME = 'crm_sessionid'`### 六、白名单与中间件1) OA 中间件 `oa/app/middleware/auth.py`
```python
if request.path_info in ["/login/", "/image/code/", "/logout/","/register/","/crm/sso/redirect/"]:return
```2) CRM 中间件 `app/midieware/auth.py`
```python
if request.path_info in ["/login/", "/image/code/", "/logout/","/register/","/oa/sso/login/","/sso/status/","/sso/debug/"]:return
```### 七、前端入口`oa/app/templates/layout.html` 导航栏:
```html
<li><a href="/crm/sso/redirect/?next=/index/" target="_blank">进入CRM系统</a></li>
```可按需调整 `next` 到 CRM 具体页面,例如 `/customer/list/`。### 八、验证步骤
1. 启动 OA 于 `127.0.0.1:8018`,CRM 于 `127.0.0.1:8009`。
2. 浏览器登录 OA `/login/`。
3. 点击 OA 顶部“进入CRM系统”。
4. 期望效果:自动跳转并登录 CRM(无需输入密码),到达 `next` 指定页面(默认 `/index/`)。
5. 联调辅助:- CRM 查看登录态:`/sso/status/`- CRM 生成调试链接:`/sso/debug/?username=<crm用户名>`### 九、安全要点
- 强制使用 HMAC-SHA256 + 共享密钥校验,避免伪造。
- 采用 `ts + nonce` 防重放,限制时间窗口(±120 秒)。
- 双站点使用不同的 `SESSION_COOKIE_NAME`,避免 Cookie 冲突。
- 生产环境务必更换 `SSO_SHARED_SECRET` 并妥善保密,不要入库或提交到公开仓库。
- 建议为 SSO 接口加上访问频率限制与审计日志。### 十、常见问题
- “跳转后提示 Invalid signature/expired”:检查两端 `SSO_SHARED_SECRET` 是否一致、机器时间是否同步、链接是否过期。
- “User not found in CRM”:确认 CRM 数据库中存在同名 `Admin.username`。
- “登录成功但显示权限不足/菜单不对”:核对 CRM 里该用户的 `role/status`。### 十一、后续可选增强
- 增加 SSO 单点登出(SLO):在一端退出同步通知另一端清理会话。
- 增加签名密钥滚动与版本号,便于安全升级。
- 通过后端存储 `nonce` 使用记录,进一步抵御重放攻击。
http://www.dtcms.com/a/390292.html

相关文章:

  • 人工智能在设备管理软件中的应用
  • __pycache__ 文件夹作用
  • 利欧泵业数据中心液冷系统解决方案亮相2025 ODCC开放数据中心峰会
  • 【论文阅读】Masked Conditional Variational Autoencoders for Chromosome Straightening
  • 天气预测:AI 如何为我们 “算” 出未来的天空?
  • 大数据管理与应用有什么注意事项?企业该如何发挥大数据的价值
  • CSS的opacity 属性
  • STM32 LwIP协议栈优化:从TCP延迟10ms降至1ms的内存配置手册
  • 【0基础3ds Max】创建标准基本体(长方体、球体、圆柱体等)理论
  • 驾驭未来:深度体验 Flet 0.7.0 的重大变革与服务化架构
  • 【Datawhale组队学习202509】AI硬件与机器人大模型 task01 具身智能基础
  • Go语言高并发编程全面解析:从基础到高级实战
  • leetcode算法刷题的第三十八天
  • RHEL 兼容发行版核心对比表
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘yaml’ 问题
  • 无刷电机有感方波闭环控制
  • 【EKL】
  • 设计模式-模板方法模式详解(2)
  • 算法(一)双指针法
  • C语言指针深度解析:从核心原理到工程实践
  • hsahmap的寻址算法和为是你扩容为2的N次方
  • ​​[硬件电路-243]:电源纹波与噪声
  • Kurt-Blender零基础教程:第1章:基础篇——第2节:认识界面
  • Kurt-Blender零基础教程:第1章:基础篇——第1节:下载与键位
  • 袋鼠参谋 - 美团推出的餐饮行业经营决策 AI 助手
  • 09-Redis 哈希类型深度解析:从命令实操到对象存储场景落地
  • 【论文阅读】MaskGIT: Masked Generative Image Transformer
  • Maya绑定基础知识总结合集:父子关系和父子约束对比
  • 从假设检验到数据驱动决策:统计推断的技术实战与方法论深度拆解
  • 基于PyTorch Geometric的图神经网络预训练模型实现