Session model stays Option B (index2sso.jsp + LtpaTokenManager). OAuth lives in custom qy.war (/qy/auth/...) under Kingdee lib/sp + easweb.ear/qy.war.
Primary reference project: BaoYPro (报业 / 泛微 E10). Prefer explicit /qy/auth/weaver/... over Unified /qy/auth/app (UA detection).
New project: complete Agent intake in SKILL.md before coding.
| Scenario | Fit |
|---|---|
| 泛微 E10 OAuth2 门户 / 待办进 sHR | Yes |
钉钉 OAuth 进 sHR(显式 /auth/dingtalk) |
Yes — same POST index2sso landing |
IdP redirect_uri must stay without .do |
Yes (Filter forwards internally) |
Rely on Unified /auth/app + User-Agent |
No for PC deep links / Weaver todos |
All /shr URLs auto OAuth without click entry |
No — use Option A |
| OTP / WeChart OTP auto login | No — use OTP2sso.jsp, not this |
Portal eassso/login?service=SHR_URL
→ sso_web login_withForm.js (keep /shr/home.do native)
→ /qy/auth/weaver/app.do?appId=&redirect=
→ state=Base64Url(redirect|appType) → 泛微 authorize
→ callback /qy/auth/callback/weaver/pa?code&state
→ CallbackSuffixCompatFilter → forward pa.do
→ code → accessToken → profile → map sHR user (PERSON_NUMBER)
→ WeaverShrLanding.writePostForm → HTML POST /shr/index2sso.jsp
→ SHR session → redirectTo
Todo / logout deep links use the same /qy/auth/weaver/app.do entry (not Unified /auth/app).
| Source | Role |
|---|---|
INTEGRATION_CONFIG_PATH → integration-config-*.json |
common.*, oauth.apps[], weaver.ecologyUrl + OAuth paths |
weaver.ecologyUrl |
authorize / accessToken / profile / logout (IdP) |
oauth.apps[].callbackUrl |
IdP redirect_uri (no .do) |
oauth.apps[].appId / appSecret |
E10 client_id / secret |
desktopRedirectType=TO_SHR |
PC → index2sso POST |
Do not put Weaver OpenAPI push secrets in this JSON — those stay in weaverTodoConfig.properties (kdshrpmsg).
Register with 泛微: exact callbackUrl string (protocol/host/port/path).
/auth/app vs WeaverAuthController| | UnifiedAuthController /auth/app | WeaverAuthController /auth/weaver/app |
|--|--|--|
| Platform select | User-Agent detectors | Explicit weaver + appId |
| PC browser from Weaver todo | Often unsupported_client | Works |
| Landing | Base doCallback often 302 Location + LTPA | POST form (WeaverShrLanding) |
| Minimize base edits | Needs UA / landing hooks in base | Keep changes in weaver package |
Rule: PC 深链 / 待办 / 门户桥 → /qy/auth/weaver/app(.do).
App WebView + reliable UA → Unified /auth/app OK for DingTalk-in-app.
Future DingTalk todo/SSO: add /qy/auth/dingtalk/... (explicit), reuse POST index2sso; do not force everything through UA-based /auth/app.
.do| Piece | Role |
|---|---|
CallbackSuffixCompatFilter on /auth/callback/* |
forward to .do, query preserved |
| Controller | Map both /callback/.../pa and /pa.do |
suffix-pattern="false" |
pa is path var |
web.xml |
*.do and / |
%2525252B)LTPA in 302 Location → Apusic multi-encode.
Fix: HTML form POST to /shr/index2sso.jsp (WeaverShrLanding.writePostForm / base writeShrSsoLoginForm). Never put LTPA password in Location.
Not classic CORS. Global filter:
{EAS_HOME}/apusic/domains/server1/config/web.xml → com.apusic.util.AttackFilter
| Param | Role |
|---|---|
enableCSRFCheck |
Master switch for Referer check |
enableCSRFCheck_URL |
Allow URI via allow_URLS when CSRF on |
serverNameWhiteList |
Referer host allow list |
allow_URLS |
Path prefixes (include /qy/ if CSRF on) |
shr_web enableSHRRequestParamWrapFilter is not cross-origin control (param wrap on /shr only).
Symptom: external Referer (Weaver) → /qy/... 404/403; no Referer / same-host → OK.
Prefer whitelist /qy/ + Weaver host over disabling CSRF globally.
logoutHR.js product chain)/qy/auth/weaver/logout.do?appId=&redirect=service = SHR SSO entryhttp://{shr}/qy/auth/weaver/app.do?appId=&redirect=encodeURIComponent(service) then jump to{ecology}/sp/integration/oauth2.0/logout?service=...Weaver docs: service domain must be on 退出重定向白名单.
Otherwise Weaver rewrites to ecology home (service=http://ecology/), login stays in Weaver (e.g. workflow center).
Whitelist at least: http://{shrHost}:{port} (e.g. http://172.16.38.1:6888).
| Piece | Role |
|---|---|
logoutHR.js 二开块 |
After local logout → /qy/auth/weaver/logout.do?appId&redirect |
WeaverAuthController.logout |
Build SSO entry as service |
WeaverShrLanding.writeLogoutThenService |
HTML + JS encode (avoid double-encode) |
Do not set service to ecology homepage. Do not expect external service to work without whitelist.
oaSsoUrl = http://{host}/qy/auth/weaver/app.do
+ appId=
+ redirect=service/target
Whitelist: /shr/home.do native. Prefer src overlay for sso_web.
- [ ] integration jar → {EAS_HOME}/server/lib/sp/
- [ ] qy.war in easweb.ear application.xml + deployed
- [ ] INTEGRATION_CONFIG_PATH; callbackUrl == 泛微注册
- [ ] login_withForm.js → /qy/auth/weaver/app.do
- [ ] logoutHR.js 二开 + 泛微 service 白名单
- [ ] AttackFilter: /qy/ allowed or CSRF off only if accepted
- [ ] ssoParamemter UrlPattern includes /index2sso.jsp
- [ ] Restart; private window for OAuth code
| Symptom | Check |
|---|---|
Callback 404 /callback/weaver/pa |
Filter + .do mapping + suffix-pattern |
%2525252B / must paste URL |
Still GET Location — deploy POST form landing |
External Referer → /qy 404 |
AttackFilter CSRF / whitelist /qy/ |
| Logout then stay in Weaver | service not whitelisted; address bar still service=ecology/ |
Logout login page service=ecology/ |
White list OR old JS/jar not deployed |
unsupported_client on /auth/app |
UA miss — use /auth/weaver/app |
| 80013 redirect_uri | callbackUrl vs IdP register mismatch |
| qy 404 always | qy.war missing from live easweb.ear |
WeaverAuthController (/auth/weaver/app, callback, logout)
WeaverOAuthStrategy, WeaverApiUtils, WeaverConfigService
WeaverShrLanding (writePostForm, writeLogoutThenService, redirectLocation)
CallbackSuffixCompatFilter
login_withForm.js → /qy/auth/weaver/app.do
logoutHR.js → /qy/auth/weaver/logout.do
integration-config-*.json (weaver + oauth)
apusic/.../config/web.xml AttackFilter
Search:
WeaverShrLanding, writeLogoutThenService, /auth/weaver/app
CallbackSuffixCompatFilter, AttackFilter, serverNameWhiteList
logoutHR.js, ecologyUrl, index2sso.jsp