泛微 EC9 对接网易企业邮箱 SSO 最终实施说明
一、实施背景
为统一身份认证,减少多系统重复登录,现将泛微 EC9 系统与网易企业邮箱进行单点登录(SSO)对接。本文档用于指导 实施、部署、运维及后续维护,可作为项目交付与内部技术留档。
二、整体技术架构
2.1 系统角色
- 泛微 EC9:身份源(SSO 发起方)
- 网易企业邮箱开放平台:SSO 接收方
- 浏览器:跳转载体
2.2 SSO 时序流程
- 用户登录泛微 EC9
- 用户点击“网易邮箱”入口
- EC9 后端调用网易接口获取 ssoAuthToken
- EC9 后端调用 ssoSign 接口生成一次性 sso_token
- 浏览器 redirect 跳转网易邮箱
- 用户免登录进入邮箱系统
三、前置条件
3.1 泛微侧
- EC9 系统已正常部署
- 用户已通过泛微统一认证登录
- 已确认使用 loginid 作为邮箱账号前缀
3.2 网易邮箱侧
- 已开通企业邮箱
- 已在“网易企业邮箱开放平台”创建应用
- 已启用 单点登录(SSO)权限
- 获取以下信息:
- appId
- appSecret
- 企业邮箱主域名(如:shineclub.cn)
四、关键技术约定
4.1 用户账号映射规则
| 泛微字段 | 网易邮箱字段 |
|---|---|
| loginid | accountName |
示例:
泛微 loginid = heqp
邮箱账号 = heqp@shineclub.cn
4.2 重要约束(必须遵守)
- Header 中 必须使用:
qiye-app-id qiye-sso-auth-token禁止 URL 编码- SSO 跳转 URL 禁止重复拼接 https://
- JSP 中 禁止在 redirect 前使用 out.print
五、核心实现说明
5.1 获取当前登录用户(EC9)
<%@ page import="weaver.hrm.User" %>
<%@ page import="weaver.hrm.HrmUserVarify" %>
HrmUserVarify.checkUser(request, response);
User user = HrmUserVarify.getUser(request, response);
String accountName = user.getLoginid();
5.2 调用网易 SSO 接口(后端)
请求头(必须)
qiye-app-id: <appId>
qiye-sso-auth-token: <原始 token,不可 encode>
Content-Type: application/json
关键接口
/api/pub/token/ssoAuthToken
/api/sso/ssoSign
5.3 最终跳转 URL 构造
String redirectUrl = endpoint + "?sso_token=" + sign + "&lang=0";
response.sendRedirect(redirectUrl);
示例:
https://entry.qiye.163.com/login/ssoLogin?sso_token=xxxxx&lang=0
六、JSP 实施示例(生产可用)
<%@ page import="weaver.hrm.User" %>
<%@ page import="weaver.hrm.HrmUserVarify" %>
<%@ page import="com.weaver.general.BaseBean" %>
<%@ page import="com.api.shineclub.netease.*" %>
<%
BaseBean log = new BaseBean();
try {
HrmUserVarify.checkUser(request, response);
User user = HrmUserVarify.getUser(request, response);
String accountName = user.getLoginid();
log.writeLog("【网易邮箱SSO】loginid=" + accountName);
String ssoUrl = new NeteaseSSOService()
.buildSSOUrl(accountName, NeteaseConfig.domain);
response.sendRedirect(ssoUrl);
return;
} catch (Exception e) {
log.writeLog("【网易邮箱SSO】异常", e);
out.print("网易邮箱单点登录失败:" + e.getMessage());
}
%>
七、日志与排错指引
7.1 推荐日志点
- 当前 loginid
- ssoAuthToken 是否获取成功
- ssoSign 接口响应
- 最终 redirectUrl
7.2 常见问题对照
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
| appId 不能为空 | Header 名错误 | 使用 qiye-app-id |
| sso token 验证失败 | token 被 encode | 禁止编码 |
| 页面无法打开 | URL 拼接错误 | endpoint 原样使用 |
| weaver_user 为 null | 未校验登录 | 使用 HrmUserVarify |
八、安全与运维建议
- SSO 接口仅部署在内网
- 日志中避免打印完整 token
- 定期检查网易应用权限有效性
- 建议配置失败兜底(跳普通登录)
九、常见问题 FAQ 与排错流程
9.1 常见问题 FAQ
Q1:访问 SSO 页面提示 appId 不能为空?
A:请求头使用了错误的 Header 名。必须使用:
qiye-app-id
而不是 appId。
Q2:提示 sso token 验证失败 (-321)?
A:qiye-sso-auth-token 被 URL 编码或被篡改。Header 中的 token 必须原样传输,禁止 URLEncoder.encode。
Q3:可以成功跳转,但网易邮箱页面打不开?
A:SSO 跳转 URL 拼接错误。endpoint 本身已包含 https://,禁止再次拼接协议头。
Q4:JSP 中获取不到当前登录用户(weaver_user 为 null)?
A:JSP 未经过泛微登录校验。必须在 JSP 中调用:
HrmUserVarify.checkUser(request, response);
Q5:页面无任何反应或偶发跳转失败?
A:在 response.sendRedirect() 前使用了 out.print,导致响应提前提交。生产环境中禁止二者同时使用。
9.2 排错流程(推荐顺序)
1. 确认泛微已登录
- 首页可正常访问
- JSP 中 HrmUserVarify.checkUser 不跳转登录页
2. 确认 loginid 获取正确
- 日志打印 user.getLoginid()
3. 确认 ssoAuthToken 接口返回 success=true
4. 确认 ssoSign 接口 Header
- 是否包含 qiye-app-id
- token 是否未编码
5. 检查最终 redirectUrl
- 是否只有一个 https://
- 是否包含 sso_token
6. 浏览器直接访问 redirectUrl 测试
十、附录
A. 关键类说明
NeteaseSSOService:封装网易 SSO 接口调用NeteaseConfig:集中配置类HrmUserVarify:泛微登录态校验
没有要显示的评论
没有要显示的评论