Adobe Air 应用程序的 cakephp 用户身份验证

发布于 2025-01-06 01:40:13 字数 202 浏览 0 评论 0原文

我有一个使用 flex 和 cakephp 开发的网络应用程序。我的客户需要使用 Adob​​e Air 制作该 Web 应用程序的桌面应用程序。柔性到空气的转换已成功完成。在 Flex 应用程序中,Flex 和 cakephp 的通信是使用远程控制器进行处理的。

在空中应用程序中,我在使用 cakephp 默认用户身份验证来验证用户身份时遇到问题。谁能帮我找到解决方案?

I have a web application developed using flex and cakephp. My client need to make a desktop application of that web application using Adobe Air. The conversion of the flex to Air is done successfully. I the flex application the communication of flex and cakephp is handled using a remotes controller.

In air application I have a problem of authenticating the user with cakephp default user authentication. Can anyone help me to find a solution for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心不设防 2025-01-13 01:40:13

我建议您通过 POST 将用户凭据发送到 cakephp 后端。

UsersController 中的登录函数看起来像这样:

public function login() {
    if ($this->Auth->login()) {
    $this->serviceResponse(Status::SUCCESS);
} else {
    $this->serviceResponse(Status::AUTH_FAILED);
    }
}

// this is just an example out of my appcontroller to send json responses
public function serviceResponse($code, $data = array()) {
    $response = compact('code', 'data');
    $this->response->body(json_encode($response));
    $this->response->send();
    $this->shutdownProcess();
    exit;
}

// I also defined a class for return statuses
class Status {
    const SUCCESS = 'success';
    const ERROR = 'error';
    ...
}

i suggest you to send your user credentials via POST to your cakephp backend.

A login function in your UsersController would look something like this:

public function login() {
    if ($this->Auth->login()) {
    $this->serviceResponse(Status::SUCCESS);
} else {
    $this->serviceResponse(Status::AUTH_FAILED);
    }
}

// this is just an example out of my appcontroller to send json responses
public function serviceResponse($code, $data = array()) {
    $response = compact('code', 'data');
    $this->response->body(json_encode($response));
    $this->response->send();
    $this->shutdownProcess();
    exit;
}

// I also defined a class for return statuses
class Status {
    const SUCCESS = 'success';
    const ERROR = 'error';
    ...
}
梦开始←不甜 2025-01-13 01:40:13

基本上,您希望将验证请求作为 ajax 请求发送。为此,您需要修改标头、通过 cookie 捕获会话 ID 并将其发布以保持会话处于活动状态。它需要从 Cake 返回一个 JSON 对象。

我创建了几个 Flex 类,用于为 Flex 移动应用程序和 CakePHP 后端实现此目的。它应该能够满足您的需求。

它位于两个文件中,AutoValidationUrlRequest.as 扩展了 HeaderURLRequest.as 文件。我并不乐观,但可能有几个变量需要改变,但总的来说,它运行得很好,并且可能只需要进行几个更改就可以在您的应用程序上运行。

要使用它,只需创建一个新的 AutoValidationUrlRequest 对象并在 headerUrlRequestComplete 事件上添加一个事件侦听器,然后运行 ​​AutoValidationUrlRequest.send(...) 进行 POST。还有一个名为convertToPostVars的方便方法,用于简单的Cake Friends Post变量。

AutoValidationUrlRequest.as:

package libs 
{

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;

import models.LocalDeviceData;
import models.Model;

import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.utils.ObjectUtil;

[Event("LoginFailed")]
[Event("MobileUserDoesNotExist")]

public class AutoValidationURLRequest extends HeaderURLRequest
{       
    public static const LOGIN_FAILED:String = "LoginFailed";
    public static const MOBILE_USER_DOES_NOT_EXIST:String = "MobileUserDoesNotExist";
    /** 
     * will automatically be set by this class, if not set will login
     */ 
    public var requestHeaders:Object = new Object();
    private var _cookie:Object;

    /** 
     * should be an object with name of the cookie variables parsed in as key/value pairs
     */
    protected function set cookie(ck:Object):void{
        _cookie = ck;
    }

    protected function get cookie():Object{
        return _cookie;
    }

    public function AutoValidationURLRequest(){

    };

    public function send(url:String, postData:Object, generateUrlVars:Boolean = true):void{
        if(generateUrlVars){
            postData = convertToPostVars(postData);
        }
        sendRequest("http://yourwebsite.com"+url, postData, requestHeaders);
    }

    override protected function parseHeaders(e:HTTPStatusEvent):void{
        super.parseHeaders(e);
        if('Set-Cookie' in headers){
            requestHeaders['Cookie'] = parseCookie(headers['Set-Cookie']);
            //requestHeaders['User-Agent'] = headers['User-Agent'];
        }
    }


    /**
     *  returns the cookie key/val string for send requests back to the server 
     */
    protected function parseCookie(cookieString:String):String{
        var cookieObj:Object = new Object();
        var cookieBits:Array = cookieString.split("; ");
        return cookieBits[0]; 

        /*
        for each(var ck:String in cookieBits){
            var cb:Array = ck.split("=");
            cookieObj[cb[0]] = cb[1];
        }
        return cookieObj;
        */
    }

}
}

HeaderURLRequest.as:

package libs 
{

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;

import mx.core.FlexGlobals;
import mx.rpc.events.ResultEvent;
import mx.utils.ObjectUtil;


[Event("headerUrlRequestComplete")]

public class HeaderURLRequest extends EventDispatcher
{
    public static const HEADERURLREQUEST_COMPLETE:String = "headerUrlRequestComplete";

    public var headers:Array = [];
    public var data:Object = new Object();
    public var variables:Object = new Object();
    public var invalidFields:Object = new Object();
    public var errorMsg:String = "";


    /**
     * the headers array must contain an object with a 'name' key and a 'value' key eg: cookie: <cookieStr>
     */
    public function HeaderURLRequest():void{
    }

    public function sendRequest(url:String, postData:Object = null, requestHeaders:Object = null):void{
        var urlLoader:URLLoader = new URLLoader()
        var urlRequest : URLRequest = new URLRequest(url);

        //make it an ajax request
        urlRequest.requestHeaders.push(new URLRequestHeader('X-Requested-With', 'XMLHttpRequest'));

        for(var header:* in requestHeaders){
            var authHeader:URLRequestHeader = new URLRequestHeader(header as String, requestHeaders[header]); 
            urlRequest.requestHeaders.push(authHeader)
        }
        var urlVariables:URLVariables = new URLVariables();
        for (var vars:* in postData){
            urlVariables[vars] = postData[vars];
        }

        urlRequest.method = URLRequestMethod.POST
        urlRequest.data = urlVariables;
        urlLoader.addEventListener(Event.COMPLETE, getData);
        urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, parseHeaders);
        urlLoader.load(urlRequest);

    }

    public function convertToPostVars(postData:Object, prependKeyName:String = ""):Object{
        var params:Object = {};
        if(prependKeyName == ""){
            params['_method'] = 'POST';
        }
        for (var item:* in postData){
            var objtype:Object = ObjectUtil.getClassInfo(postData[item]);
            if(objtype.name == "Object"){
                var modelKeyName:String = prependKeyName+"["+item+"]";
                var subParams:Object = convertToPostVars(postData[item],modelKeyName);
                params = merge(params, subParams);
            }else{
                params["data"+prependKeyName+"["+item+"]"] = postData[item];
            }
        }
        return params;
    }

    public function flashErrorMsg():String{
        var err:String = errorMsg;
        errorMsg = "";
        return err;
    }

    protected function parseHeaders(e:HTTPStatusEvent):void{
        var i:Number=0;
        headers = [];
        for each(var header:URLRequestHeader in e.responseHeaders){
            headers[header.name] = header.value;
        i++;
        } 
    }

    protected function getData(e:Event):void{
        //trace('data: ');
        if(e.currentTarget.data == ''){
            e.currentTarget.data = '{}';
        }
        data = JSON.parse(e.currentTarget.data);

        //trace(ObjectUtil.toString(data));
        if(data.hasOwnProperty('variables')){
            variables = data.variables;
            if (variables != null){
                if(variables.hasOwnProperty('invalidFields')){
                    invalidFields = variables.invalidFields;
                    for (var error:String in invalidFields){
                        errorMsg += invalidFields[error] + "\n\n";
                    }
                }
            }else{
                //no variable data found!!
            }
        }
        dispatchEvent(new Event(HEADERURLREQUEST_COMPLETE));
    }   

    public function isEmpty(obj:Object){
        var isEmpty:Boolean = true;
        for (var n in obj) { isEmpty = false; break; }
        return isEmpty;
    }

    public function merge( obj0:Object, obj1:Object ):Object
    {
        var obj:Object = { };
        for( var p:String in obj0 )
        {
            obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];
            //trace( p, ' : obj0', obj0[ p ], 'obj1', obj1[ p ], '-> new value = ', obj[ p ] );
        }
        for (var p1:String in obj1){
            if(!obj.hasOwnProperty(p1)){
                obj[ p1 ] =  obj1[ p1 ] ;
            }
        }
        return obj;
    }
}
}

另外,将其与我的 Jose Gonzalez 的 CakePHP ajax_controller 插件的分叉版本 一起使用是真的很方便。它基本上接受任何 Ajax 请求并转换所有视图变量并将它们输出到 JSON 对象,而不渲染视图。否则,如果您不使用 ajax 请求,Cake 将正常渲染视图。祝你好运!

Basically, you want to send the validation request as an ajax request. To do that you need to modify headers, capture session ids through cookies and post them to keep the session alive. It expects a JSON object returned from Cake.

I've created a couple Flex classes that achieve just this for a Flex Mobile App and a CakePHP backend. It should work the same for your needs.

It's in two files, the AutoValidationUrlRequest.as extends the HeaderURLRequest.as file. I'm not positive but there may be a couple variables to change, but overall it works very well and probably won't take more than a couple changes to get it working on your app.

To use it, simply create a new AutoValidationUrlRequest object and add an event listener on the headerUrlRequestComplete Event and then run AutoValidationUrlRequest.send(...) to POST. there is also a handy method called convertToPostVars for easy Cake Friendly Post variables.

AutoValidationUrlRequest.as:

package libs 
{

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;

import models.LocalDeviceData;
import models.Model;

import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.utils.ObjectUtil;

[Event("LoginFailed")]
[Event("MobileUserDoesNotExist")]

public class AutoValidationURLRequest extends HeaderURLRequest
{       
    public static const LOGIN_FAILED:String = "LoginFailed";
    public static const MOBILE_USER_DOES_NOT_EXIST:String = "MobileUserDoesNotExist";
    /** 
     * will automatically be set by this class, if not set will login
     */ 
    public var requestHeaders:Object = new Object();
    private var _cookie:Object;

    /** 
     * should be an object with name of the cookie variables parsed in as key/value pairs
     */
    protected function set cookie(ck:Object):void{
        _cookie = ck;
    }

    protected function get cookie():Object{
        return _cookie;
    }

    public function AutoValidationURLRequest(){

    };

    public function send(url:String, postData:Object, generateUrlVars:Boolean = true):void{
        if(generateUrlVars){
            postData = convertToPostVars(postData);
        }
        sendRequest("http://yourwebsite.com"+url, postData, requestHeaders);
    }

    override protected function parseHeaders(e:HTTPStatusEvent):void{
        super.parseHeaders(e);
        if('Set-Cookie' in headers){
            requestHeaders['Cookie'] = parseCookie(headers['Set-Cookie']);
            //requestHeaders['User-Agent'] = headers['User-Agent'];
        }
    }


    /**
     *  returns the cookie key/val string for send requests back to the server 
     */
    protected function parseCookie(cookieString:String):String{
        var cookieObj:Object = new Object();
        var cookieBits:Array = cookieString.split("; ");
        return cookieBits[0]; 

        /*
        for each(var ck:String in cookieBits){
            var cb:Array = ck.split("=");
            cookieObj[cb[0]] = cb[1];
        }
        return cookieObj;
        */
    }

}
}

HeaderURLRequest.as:

package libs 
{

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;

import mx.core.FlexGlobals;
import mx.rpc.events.ResultEvent;
import mx.utils.ObjectUtil;


[Event("headerUrlRequestComplete")]

public class HeaderURLRequest extends EventDispatcher
{
    public static const HEADERURLREQUEST_COMPLETE:String = "headerUrlRequestComplete";

    public var headers:Array = [];
    public var data:Object = new Object();
    public var variables:Object = new Object();
    public var invalidFields:Object = new Object();
    public var errorMsg:String = "";


    /**
     * the headers array must contain an object with a 'name' key and a 'value' key eg: cookie: <cookieStr>
     */
    public function HeaderURLRequest():void{
    }

    public function sendRequest(url:String, postData:Object = null, requestHeaders:Object = null):void{
        var urlLoader:URLLoader = new URLLoader()
        var urlRequest : URLRequest = new URLRequest(url);

        //make it an ajax request
        urlRequest.requestHeaders.push(new URLRequestHeader('X-Requested-With', 'XMLHttpRequest'));

        for(var header:* in requestHeaders){
            var authHeader:URLRequestHeader = new URLRequestHeader(header as String, requestHeaders[header]); 
            urlRequest.requestHeaders.push(authHeader)
        }
        var urlVariables:URLVariables = new URLVariables();
        for (var vars:* in postData){
            urlVariables[vars] = postData[vars];
        }

        urlRequest.method = URLRequestMethod.POST
        urlRequest.data = urlVariables;
        urlLoader.addEventListener(Event.COMPLETE, getData);
        urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, parseHeaders);
        urlLoader.load(urlRequest);

    }

    public function convertToPostVars(postData:Object, prependKeyName:String = ""):Object{
        var params:Object = {};
        if(prependKeyName == ""){
            params['_method'] = 'POST';
        }
        for (var item:* in postData){
            var objtype:Object = ObjectUtil.getClassInfo(postData[item]);
            if(objtype.name == "Object"){
                var modelKeyName:String = prependKeyName+"["+item+"]";
                var subParams:Object = convertToPostVars(postData[item],modelKeyName);
                params = merge(params, subParams);
            }else{
                params["data"+prependKeyName+"["+item+"]"] = postData[item];
            }
        }
        return params;
    }

    public function flashErrorMsg():String{
        var err:String = errorMsg;
        errorMsg = "";
        return err;
    }

    protected function parseHeaders(e:HTTPStatusEvent):void{
        var i:Number=0;
        headers = [];
        for each(var header:URLRequestHeader in e.responseHeaders){
            headers[header.name] = header.value;
        i++;
        } 
    }

    protected function getData(e:Event):void{
        //trace('data: ');
        if(e.currentTarget.data == ''){
            e.currentTarget.data = '{}';
        }
        data = JSON.parse(e.currentTarget.data);

        //trace(ObjectUtil.toString(data));
        if(data.hasOwnProperty('variables')){
            variables = data.variables;
            if (variables != null){
                if(variables.hasOwnProperty('invalidFields')){
                    invalidFields = variables.invalidFields;
                    for (var error:String in invalidFields){
                        errorMsg += invalidFields[error] + "\n\n";
                    }
                }
            }else{
                //no variable data found!!
            }
        }
        dispatchEvent(new Event(HEADERURLREQUEST_COMPLETE));
    }   

    public function isEmpty(obj:Object){
        var isEmpty:Boolean = true;
        for (var n in obj) { isEmpty = false; break; }
        return isEmpty;
    }

    public function merge( obj0:Object, obj1:Object ):Object
    {
        var obj:Object = { };
        for( var p:String in obj0 )
        {
            obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];
            //trace( p, ' : obj0', obj0[ p ], 'obj1', obj1[ p ], '-> new value = ', obj[ p ] );
        }
        for (var p1:String in obj1){
            if(!obj.hasOwnProperty(p1)){
                obj[ p1 ] =  obj1[ p1 ] ;
            }
        }
        return obj;
    }
}
}

Also, using this with my forked version of Jose Gonzalez's CakePHP ajax_controller plugin is really handy. It basically takes any Ajax Request and converts all view variables and outputs them into a JSON object, no rendered view. Otherwise, if you're not using an ajax request, Cake will render the views normally. Good Luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文