WSO2 7.0.0版本Identifier First登录流程异常问题问询
解决方案:WSO2 v7.0.0 跨应用登录自动填充用户名/标识步骤完成状态
问题背景
- 环境:WSO2 v7.0.0
- 登录流程:步骤1(Identifier First)→ 步骤2(用户名密码验证,使用条件认证脚本)
- 场景:用户已登录一个应用后,打开新标签页访问同WSO2实例保护的另一应用,WSO2检测到活跃会话跳过步骤1,但仍要求用户重复输入用户名
- 核心问题:
- 能否自动将
context.currentKnownSubject.identifier传入步骤2作为主体标识符,避免重复输入? - 能否传入自定义参数(如"idf")到login.jsp,让页面识别步骤1已完成?
- 能否自动将
针对问题1的解决方案:自动填充用户名到步骤2
在条件认证脚本中,先检测是否存在活跃会话的已知主体,若存在则直接将用户名传递到步骤2,实现自动填充并跳过步骤1。
修改后的完整脚本
var onLoginRequest = function(context) { var reqId = null; var usernameForRegistration = null; // 优先检查活跃会话的已知主体 if (context.currentKnownSubject) { var subject = context.currentKnownSubject; Log.info("检测到活跃会话,主体标识符:" + subject.identifier); // 直接触发步骤2并传递用户名参数 executeStep(2, { params: { username: [subject.identifier] } }); return; // 终止后续流程 } // 原步骤1执行逻辑 executeStep(1, { onSuccess: function(context) { subject = context.currentKnownSubject; Log.info("POST-TRACE known subject: " + subject.identifier); Log.info("POST-TRACE known subject: " + subject.username); var usernameParam = context.request.params.username; var usernameInput = (usernameParam && usernameParam.length > 0) ? usernameParam[0] : null; Log.info("POST-TRACE Username input: " + usernameInput); if (usernameInput) { var isMobile = usernameInput.match(/^\+?[0-9]{10,15}$/); var userExists = false; try { if (isMobile) { Log.info("POST-TRACE User input detected as mobile"); var claims = {}; claims['http://wso2.org/claims/mobile'] = usernameInput; var user = getUniqueUserWithClaimValues(claims, context); userExists = (user != null); } else { Log.info("POST-TRACE User input detected as email or username"); var claims = {}; claims['http://wso2.org/claims/emailaddress'] = usernameInput; var user = getUniqueUserWithClaimValues(claims, context); userExists = (user != null); } if (userExists) { if (isMobile) { executeStep(3); } else { // 首次登录时也传递用户名到步骤2填充 executeStep(2, { params: { username: [usernameInput] } }); } } else { Log.info("POST-TRACE User not found"); reqId = "REQ-" + Math.floor(Math.random() * 1000000000); usernameForRegistration = usernameInput; httpPost('https://custom-registration-portal.com/register/request-id', { "requestID": reqId }, { "X-API-Key": "sdfsf12345" }, { onSuccess: function(context, data) { Log.info('httpPost call succeeded'); sendError( 'https://custom-registration-portal.com/register', { 'callback': 'http://my-sample-web.com/Response/EAE', 'value': usernameForRegistration, 'requestID': reqId, 'clientID': 'someClientID' } ); }, onFail: function(context, data) { Log.info('httpPost call failed'); // 自定义失败处理逻辑 } }); } } catch (e) { Log.info("POST-TRACE Exception while checking user: " + e.message); } } else { Log.info("POST-TRACE username : " + usernameParam); } } }); };
原理说明
context.currentKnownSubject会在存在有效活跃会话时自动填充用户信息;executeStep的params参数可传递请求参数到指定步骤,步骤2的登录页面会自动读取username参数并填充到输入框;- 优先检查活跃会话逻辑,直接跳过步骤1,完全匹配你的场景需求。
针对问题2的解决方案:传递自定义标识参数到login.jsp
若需传递自定义参数(如"idf")到login.jsp,只需在执行步骤2时添加对应参数即可:
关键代码修改
在触发步骤2的位置,添加inputType参数:
// 活跃会话场景 executeStep(2, { params: { username: [subject.identifier], inputType: ["idf"] } }); // 首次登录场景 executeStep(2, { params: { username: [usernameInput], inputType: ["idf"] } });
login.jsp适配逻辑
你的login.jsp已存在String inputType = request.getParameter("inputType");,可直接基于该参数做业务处理,例如:
<% String inputType = request.getParameter("inputType"); String username = request.getParameter("username"); if ("idf".equals(inputType) && username != null) { // 标记步骤1已完成,隐藏用户名输入框或设置为只读 out.println("<input type='hidden' name='username' value='" + username + "'>"); out.println("<p>已识别登录状态,只需输入密码即可</p>"); } else { // 正常显示用户名输入框 out.println("<input type='text' name='username' placeholder='请输入用户名/邮箱/手机号'>"); } %>
注意事项
- 确保WSO2 v7.0.0的会话配置正确,
context.currentKnownSubject在活跃会话场景下能正常获取用户标识; executeStep的params值需为数组类型(如[subject.identifier]),与context.request.params的结构保持一致;- 测试前需清除浏览器缓存和WSO2服务器会话,确保逻辑触发准确。
内容的提问来源于stack exchange,提问作者rizaldi habibie
相关产品推荐
相关产品推荐

