1) 应用程序类型:手机银行
2) 现有 Worklight 版本:6.1 (Consumer Edition)
3) Cordova 版本:3.1.0
4) 支持平台:Android 4.2+、iOS 7+
5) 服务器操作系统:Window Server 2008
6) 应用程序服务器: IBM WebSphere Liberty Profile
7) 数据库: IBM DB2
应用程序是使用自定义挑战处理程序实现的,以对来自 IBM WebSeal 的用户进行身份验证,ChallengeHandler 向 IBM WebSeal 触发 HTTPS 请求以执行以下操作:
- 从 IBM WebSeal 获取登录参数(例如登录页面类型、登录表单提交 URL)
- 交换加密密钥(在 HTTPS 之上,银行要求使用 jCryption 进一步加密流量)
- 提交加密的用户名/密码
上述所有步骤都是使用 jQuery 的 ajax()、post() 或 getJson() 函数实现的,它在上述设置中完美运行。
问题
Worklight 6.1 升级到 MobileFirst 7.1 后,上述身份验证方法不再适用于 Android 设备,而 iOS 仍按预期工作。
在花了几天时间对详细的请求和响应日志进行故障排除之后,我们得出的结论是,在 jQuery 的 ajax() post() 和 MobileFirst HTTP 请求之间,Android 具有不同的 Cookie 管理上下文。
示例:
通过使用 WLJQ.ajax(... myUrl ...) 生成 Set-Cookie 响应,当请求在匹配域中时,Cookie 将自动附加到所有子序列 ajax 请求。
但是来自 ajax() 请求的 Set-Cookies 响应标头不会影响以下 MobileFirst HTTP 请求函数: 1. ChallengeHandler.submitLoginForm
2. WL.Client.invokeProcedure
3. WL.Client.login
我们的 ChallengeHandler 使用 cookie 值对用户进行身份验证并记住用户,但由于 cookie 不会在 MobileFirst 和 jQuery 之间共享,因此 IBM WebSeal 将阻止对 WL.Client.InvokeProcedure 的调用,因为请求被识别为未经身份验证用户。
我们还观察到 jQuery ajax/post 的用户代理与上述 MobileFirst 函数有很大不同:
MobileFirst 用户代理:Dalvik/2.1.0 (Linux; U; Android 6.0.1; SM-G925F Build/MMB29K)/Worklight/7.1.0.0 WLNativeAPI(zerolte; MMB29K.G925FXXU3DPCN; SM-G925F; SDK 23; Android 6.0 .1)
jQuery(在三星 Galaxy S6 上运行)
用户代理:Mozilla/5.0(Linux;Android 6.0.1;SM-G925F Build/MMB29K;wv)AppleWebKit/537.36(KHTML,如 Gecko)版本/4.0 Chrome/49.0.2623.105 移动Safari/537.36/Worklight/7.1.0.0
故障排除总结
1) 更新安卓的 CookieManager 以接受第三方 cookie
CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptThirdPartyCookies(webView, true);
2) 使用 WL.Client.setCookie 从 jQuery post() 手动检索 cookie 值并附加到 MobileFirst 函数
但由于浏览器限制,我们无法检索 Set-Cookie 标头值
3) 将所有 jQuery 调用转换为使用 challengeHandler.submitLoginForm,但是使用这种方法,MobileFirst 会话在每次调用上述代码后都会重置,因此它仍然无法正常工作。