0

When our app is started up within a secured Wifi and the smartphone user did not authenticate with that Wifi Login/Captive Portal yet, the WL.Client.connect as well as connectOnStartup receive the HTML page of the portal for their connection request.

It seems the process/WL Framework is not stable in such a situation (see below). The problem is that the App does not end up in the onSuccess or onFailure procedures that we passed in as options object - there is a default Dialog being shown by Cordova/Worklight to the end user. This dialog even allows to view details of the request and the app environment.

So far, we did not find any event or hook to capture such an error situation.

( UPDATE Sept. 18: in the iOS native Objective-C WL Client Library this behavior is not the same - there: the onSuccess method is called in case of WL.Client.connect and the onFailure in case of invokeProcedure )

Does anyone know how we could catch this error/exception?

enter image description here

enter image description here

09-05 10:27:48.526: D/App(8590): ondeviceready event dispatched
09-05 10:27:48.546: D/App(8590): wlclient init started
09-05 10:27:48.546: D/App(8590): Read cookies: null
09-05 10:27:48.546: D/App(8590): CookieMgr read cookies: {}
09-05 10:27:48.566: D/App(8590): before: app init onSuccess
09-05 10:27:48.566: D/App(8590): in startBusyIndicator
09-05 10:27:48.566: D/App(8590): busyIndicator is null or not visible, so create and show
09-05 10:27:48.566: D/App(8590): Exiting startBusyIndicator: [object Object]
09-05 10:27:48.566: D/App(8590): Call WL.Client.connect establish connection and trigger the direct update check
09-05 10:27:48.576: D/App(8590): Request [http://XXX:8080/apps/services/api/App/android/init]
09-05 10:27:48.596: D/App(8590): after: app init onSuccess
09-05 10:27:48.596: D/App(8590): wlclient init success
09-05 10:27:48.637: E/external/webkit/Source/WebKit/android/WebCoreSupport/WebRequest.cpp(8590): startReading called with a nonzero buffer
09-05 10:27:48.637: E/external/webkit/Source/WebKit/android/WebCoreSupport/WebRequest.cpp(8590): Read called with a nonzero buffer
09-05 10:27:48.667: D/App(8590): response [http://XXX:8080/apps/services/api/App/android/init] success: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
09-05 10:27:48.667: D/App(8590): <html xmlns="http://www.w3.org/1999/xhtml">
09-05 10:27:48.667: D/App(8590): <head>
09-05 10:27:48.667: D/App(8590): <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
09-05 10:27:48.667: D/App(8590): <title>Untitled Document</title>
09-05 10:27:48.667: D/App(8590): <style type="text/css">
09-05 10:27:48.667: D/App(8590):         
09-05 10:27:48.667: D/App(8590):               <p align="center"><strong>App </strong><strong>HotSpot WiFi Access</strong></p>
09-05 10:27:48.667: D/App(8590):               <div id="center_this">
09-05 10:27:48.667: D/App(8590):                 
09-05 10:27:48.667: D/App(8590):                 <div id="rules_window">
09-05 10:27:48.667: D/App(8590):                 
09-05 10:27:48.667: D/App(8590): 
09-05 10:27:48.667: D/App(8590):                 <p align=center style='text-align:center'><b>Terms of Use</b></p>
09-05 10:27:48.667: D/App(8590):                             <p>NOTICE: PLEASE READ CAREFULLY. THE FOLLOWING CONSTITUTES</p>
09-05 10:27:48.667: D/App(8590):                       
09-05 10:27:48.687: E/App(8590): [http://XXX:8080/apps/services/api/App/android/init] exception. Cannot read property 'userInfo' of null
09-05 10:27:48.857: V/webview(8590): SCROLL_TO_MSG_ID
09-05 10:27:48.857: V/webcore(8590): CLEAR_HISTORY arg1=0 arg2=0 obj=null
09-05 10:27:48.927: D/CordovaLog(8590): Uncaught TypeError: Cannot read property 'userInfo' of null
09-05 10:27:48.927: E/Web Console(8590): Uncaught TypeError: Cannot read property 'userInfo' of null at file:///data/data/com.App/files/www/default/wlclient/js/worklight.js:1487
09-05 10:27:50.489: D/DroidGap(8590): onMessage(spinner,stop)
4

2 回答 2

0

您需要实现一个挑战处理程序来处理您的登录表单。请参阅此培训模块 - http://public.dhe.ibm.com/software/mobile-solutions/worklight/docs/v600/08_02_Form_based_authentication.pdf

唯一的区别是您的网关而不是 WL 服务器返回的登录表单,但从客户端的角度来看,这并不重要。

于 2013-09-06T01:47:37.910 回答
0

感谢 Anton 的提示,我们尝试了挑战处理程序。不幸的是,WL InfoCenter 5.0.6.1 http://pic.dhe.ibm.com/infocenter/wrklight/v5r0m6/index.jsp和 6.0 http://pic.dhe.ibm.com/infocenter中缺少整个 ChallengeHandler 文档/wrklight/v6r0m0/

要求是为所有“Captive Portal”、“Authentication Portal”、“Proxy Redirect”等情况构建“Catch All”解决方法,其中 HTML 代码由代理/网关/等返回到应用程序,而不是来自应用程序尝试调用的 WL 服务器的有效/预期响应。它需要适用于 WL 应用程序可能在全球任何 WIFI 网络(商业、机场、公共、酒店等)上遇到的所有情况。在任何这些情况下,在“Connect”和“InvokeProcedure”处与 WL 服务器的连接都将接收 HTML 代码,并且如果未捕获到 WL 默认对话框,则将显示该对话框。

基于示例,我们将以下代码添加到我们的 initOptions.js 中:

var LoginFormChallengeHandler = WL.Client.createChallengeHandler();

LoginFormChallengeHandler.isCustomResponse = function(response) {
    WL.Logger.debug("isCustomResponse");

    if (!response || response.responseText === null) {
        WL.Logger.debug("ChallengeHandler :: null");
        return false;
    }

    if ((response.status == 200) && (response.responseText.indexOf("/*-secure-") === -1)) {
        WL.Logger.debug("ChallengeHandler :: received");
        app.handleChallenge(response);
        return true;
    } else {
        WL.Logger.debug("ChallengeHandler :: no received");
        return false;
    }

};

LoginFormChallengeHandler.handleChallenge = function(response) {    
    WL.Logger.debug("ChallengeHandler :: handleChallenge");
}; 

和我们的 app.js

 app.handleChallenge = function(response){
        app.stopBusyIndicator();
        if(document.URL.indexOf("App.html") !== -1){            
            app.onServerRequestFailed(function(){$.mobile.changePage(app.getInitialPage());});
        }else{
            var options = app.stack.pop();
             if (options.suppressAlertOnConnectionFailure) {
                 if (options.onFailure)
                     options.onFailure(response);
             }else{
                 if (options.onFailure)
                     app.onServerRequestFailed(options.onFailure(response));
                 else
                     app.onServerRequestFailed();
             }
        }   
    };

我们尚未在生产环境中测试此代码,并做出了一些可能无效的假设:

  • 我们正在接收的响应中检查“/*-secure-”字符串值。到目前为止,我们还没有看到任何不包含此字符串的有效 WL 服务器响应。但可能存在没有该字符串的 WL 服务器响应,则此解决方法将中断,有效响应将被视为无效,并将作为错误/异常处理。

  • 我们正在使用我们的app.handleChallenge函数处理错误/异常,该函数已经在isCustomResponse函数中,而不是在LoginFormChallengeHandler.handleChallenge函数中。这是因为我们需要捕获Wl.Client.connect、connectOnStartup 以及 invokeProcedure错误/异常情况。在我们的试验中,LoginFormChallengeHandler.handleChallenge函数仅在Wl.Client.connect、connectOnStartup案例中被调用,而不在invokeProcedure案例中被调用。(见后续问题:https ://stackoverflow.com/questions/18879189/wl-5-0-6-1-js-vs-ios-native-handlechallenge-only-called-at-first-communicat )

  • isCustomResponse函数中返回true时, Wl.Client.connect、connectOnStartup 和 invokeProcedure的原始执行线程将停止,并且执行isCustomResponse函数(在Wl.Client.connect、connectOnStartup情况下还有handleChallenge函数)。这意味着开发人员提供的onSuccess 或 onFailure永远不会被调用,所有处理都需要在这些挑战处理函数中完成。我们的解决方案是在调用Procedure之前推送我们创建的选项对象到一个全局 JavaScript 数组堆栈中,并从我们的app.handleChallenge函数中的堆栈中弹出它,以便我们自己手动调用options.onFailure(response)。我们假设我们的 WL 服务器调用的调用序列和响应返回保持同步 - 否则这个基于堆栈的解决方案将会中断。

此解决方案可能不是此解决方法的最佳和推荐解决方案,但由于 WL 框架根本不处理此类情况,因此它可能是一个很好的开始方法。

当然,如果您的应用程序实际上有一个登录表单并且需要一个实际的挑战处理程序,那么在捕获所有其他 WIFI 重定向案例之前捕获您自己的登录表单会变得更加复杂!

于 2013-09-10T22:03:02.007 回答