2013-01-09 56 views
10

我正在构建一个使用REST API从服务器上的我的网站加载数据的PhoneGap中构建的简单应用程序(因为您无法在PhoneGap中运行PHP)。从CakePHP处理对PhoneGap应用程序的身份验证

上市的一些数据可能是一个例子:

$.ajax({ 
    url: 'http://myserver.com/posts/index.json', 
    dataType: 'jsonp', 
    success: function(data) { 
     for (var i=0,total=data.length; i<total; i++) 
     { 
      console.log(data.Post.title[i]); 
     } 
    } 
}); 

这是罚款和返回的数据可以在我的PhoneGap应用程序中使用。然而让我们说,帖子列表要求您登录...

我该如何处理?因为与正常的身份验证请求不同,它会重定向到登录表单,在我的JSON世界中,这不会发生。实际上发生的是实际的HTML登录表单被返回,然后导致错误,因为我的JavaScript期望JSON而不是HTML。

是否有处理此问题的最佳做法,例如,如果要求进行身份验证,那么会在PhoneGap应用程序中加载登录表单视图,而不是从应用程序返回HTML登录表单,因为它目前正在执行该操作?也许通过JSON发送一个auth请求?

举个例子简单JSONized方法是这样的:

public function index() { 
    $this->set('posts', $this->paginate()); 
    $this->set('_serialize', array('posts')); 
} 

而且如前所述我可以传递方法的名称为$this->Auth->allow()保护在beforeFilter此方法。所以我假设我需要在beforeFilter中做一些聪明的事情来知道请求是否是JSON,如果是,那么检查该方法是否需要授权,然后如果是这样,或者发回错误(而不是HTML格式,如Cake通过AuthComponent)在JSON中或允许访问。

更新:2012年1月13日

在这个问题上做一些研究多之后,我看了看Forrst API,因为他们似乎已经建立有效的什么,我希望建立一个RESTful的条款API。

例如,他们有一个电话,如:https://forrst.com/api/v2/post/comments?tiny_id=HUD这基本上是说用HUD的微小ID显示帖子的评论。你将得到的返回是,如果你没有通过认证的情况如下:

{"resp":{"error":"this method requires authentication"},"stat":"fail","in":0.0903,"authed":false,"authed_as":false,"env":"prod"} 

现在最有趣的部分是,即使我登录到Forrst我仍然会得到错误信息,因为它不是在看我的会议,而该公司预计,一种用于验证实际请求的令牌。例如?access_token=550e8400-e29b-41d4-a716-446655440000

所以我想这里的主要问题是,我如何将它建立到我的Cake App中?该计划如下:

在我的应用程序,它会重定向到登录页面,无论你通过AJAX或浏览器请求它。 Forrst处理两者,并且在调用它的API时总是返回JSON错误,并且不会返回HTML!这是我想要实现的目标。我为我的用户表添加了一个access_token列(出于安全原因,每当有人更新密码时,该列就会更改)。下一步是A)为受保护的方法检查此访问令牌,并允许或拒绝它是否正确,然后B)当没有令牌存在或不正确时需要进行一些处理,并发送正确的错误状态而不是HTML登录形成。

+0

如果我正确理解你,你正在为Forrst本身构建一个应用程序?或者您是否将Forrst用作您的用户管理系统?我有Cordova(Phonegap)和CakePHP的经验,所以我可以帮助你,但这个问题并不是100%清楚。你能分享一个链接到你正在使用的确切的API吗?因为我能找到关于这个API的唯一信息是https://forrst.com/api,但它似乎是一个访问他们的帖子的API,而不是一个用户管理系统。所以我不明白你的第一个使用'myserver.com'的代码段和'forrst.com'之间的关系。 – Jelmer

+0

对不起,我只是用Forrst作为我试图创建的API功能的一个例子。特别是JSON的验证部分返回。 **我没有使用任何来自Forrst。** – Cameron

+0

好的,看看我的答案。我希望它能以某种方式帮助你:) – Jelmer

回答

1

jQuery ajax()函数使您能够通过使用用户名和密码(http://api.jquery.com/jQuery.ajax/)将请求和请求一起传递,使用这些和处理验证失败的错误:

+0

我的应用程序如何知道何时请求身份验证?因为它目前只是将HTML表单返回给PhoneGap应用程序。 – Cameron

+0

您是否在说如果您的ajax调用未通过身份验证参数,并且需要身份验证,那么您会在没有任何指示需要身份验证的情况下反弹到原始html登录页面? – ElasticThoughts

2

从我能理解的是,您需要某种方式来返回一些错误消息,如用户未登录所需的以json格式登录。您可以执行的操作是您可以构建一个功能,如:

public function index ($token=NULL) 
{ 
    if($token != NULL) 
    { 
    // call some method to check if token is valid 
    // do required processing 
    } 
    else 
{ 
    $response=array('response'=>'failure','message'=>'Login required'); 
    echo json_encode($response); 
} 

在Ajax调用:

url: 'http://myserver.com/posts/index.json/'+token; 

在用户表中,在用户注册时,简单地生成一些accesstoken并将其存储在一列中称为'accesstoken'。

此令牌返回时。

用户登录所以,您可以在发送请求添加到您的AJAX调用。

说showPosts方法posts控制器在你的Ajax调用 http://yourdomain.com/posts/showPosts 然后

$method=$this->action; //this fetches the name of the method called             
$Mmethods =array('showPosts','test2'); // methods requiring login                
if(in_array($method,$Mmethods)) {         
$this->params array will give you all the parameters passed in URL. 
//Fetch the access token from this array if it is set in 'url' index //of this array.       
//if token is found, run sql query whether it exists in database or //not, else return response with errors and exit;} 
+0

$ method = $ this-> action; $ Mmethods = array('test1,''test2'); //数组中包含需要访问令牌的方法的名称在控制器的beforeFilter()函数中,可以这样做:if(in_array($ method,$ Mmethods)){//检查访问令牌//如果未找到令牌,返回错误并退出; } – cartina

+0

你能展示一个更完整的例子吗?不太了解这将如何工作。谢谢。 – Cameron

+0

Beforefilter()方法在调用控制器中的每个其他方法之前被调用。所以如果用户访问令牌无效,我们将使用exit;语句停止将控制权传递给控制器​​中的请求方法。另一方面,如果它是有效的,控制将传递给控制器​​中的请求方法。你是否在cakephp或其他地方的某个控制器中执行了需要执行的操作? – cartina

2

为了区别起见:你的用户需要“登录”,以在任何情况下查看返回岗位,或只有一些帖子要求用户登录?你对另一边的剧本有控制吗?(index.json)

从我现在的理解我会使用PhoneGap应用程序中的一个页面来“登录”,然后存储和发送信息以及请求到服务器index.json或更好的PHP脚本,可以处理并返回适当的json字符串。基本上,Session Cookies如何在典型的浏览器中工作。

另一种选择是,你可以修改index.json返回包含一个信息,即你​​能赶上,阅读和处理在PhoneGap的一个json字符串,然后在需要时显示应用中的用户登录表单,然后做一样的以上段落。

我愿意帮助您的代码和示例,但是您当前的帖子对您​​当前的代码和服务器返回的内容很模糊。

+0

index.json只是一个例子。但基本上我需要知道一个方法是否需要身份验证,如果是,请将这些信息传回给我的应用程序,以便我执行登录。目前它正在传递登录表单本身,这是我想要停止的。另一个问题是,如果我添加一些额外的JSON来说用户是否登录,我只想关心这个保护方法,如果这是有道理的。代码示例将非常感谢。 – Cameron

+0

关于返回的内容。如果该方法没有被保护,那么它只是为帖子返回一个简单的json对象。如果它受到保护,那么我的Cake应用程序将返回实际的HTML登录视图HTML。 – Cameron

+0

如果你看看我上面更新的帖子,你可以看到我引用了Forrst API。这正是我想要有效实现的目标。 – Cameron

4

我们对我们的应用程序也有同样的问题,建立在Phonegap中(现在称为Cordova)。让身份验证正常工作真的很痛苦,但最终我们设法通过使用Facebook API来实现它,但我认为你不想使用Facebook。

所以,如果它是你可以做的就是简单检查哪些运行下面的代码片段一个XMLHttpRequest:

PostsController - 指数()

if ($this->RequestHandler->isAjax() == 1){ 
    // This is an Ajax call 
    $this->layout = 'json'; 
    $this->set('data', array('data', 'to', 'parse')); 
} else { 
    // This is the normal request 
    # do the stuff you want to do here as usual 
} 

但由于这会问你登录,因为它不在$this->Auth->allow()列表中,它甚至不会到达那里,除非你已经登录。所以你需要做的是做一个新的AjaxController处理第一个请求。简单地把上面的代码放在beforeFilter中,并从那里做你的魔力。从那里你可以简单地检查是否有人登录,以及用户的当前状态。如果他已经登录并且想要返回数据。您可以调用您需要的模型或使用requestAction('/path/to/what/i/need')调用控制器功能,您需要的路径可以在您通过Ajax调用发送的后期变量中声明。

ajax layout,你可以告诉json_encode$data然后将被正确解析。

应用

现在在你的JavaScript,你会得到一些数据。假设您使用以下键构造返回的JSON字符串:statusdata

假设status已经在返回的JSON中设置为auth,您知道您需要进行身份验证,因此您可以显示一个登录表单,然后处理所有这些信息。只需在应用程序中创建一个漂亮的登录视图,以便您可以控制它的每个方面,并希望更安全。

如果status设置为success,则可以相应地显示所有帖子。

我有一个答案到另一个话题,我展示了如何创建我们自己的API,也许可以帮助你以某种方式:https://stackoverflow.com/a/11422866/1110760

警告的JavaScript似乎是安全的PhoneGap的应用程序,但它不是!任何人都可以从它的Android设备下载.apk文件,然后在Android emulator中打开它,然后他可以查看所有JavaScript和HTML代码。因此,要谨慎处理要直接写入JavaScript的数据以及您的API的访问方式。


我知道我的答案是有点模糊,所以如果您需要更多关于这个答案的更多信息,请咨询!

+0

这似乎是非常手动的...我可以不添加的东西在AppController附加JSON请求与附加数据,如状态,身份验证等?否则,我通过调用另一个控制器在另一个控制器中调用某个方法来打破惯例。 – Cameron

+0

@Cameron你可以在你的控制器中进行检查,或者制作一个处理这些东西的组件。就像一个叫做'isApi()'的主函数的ApiComponent,所以你可以检查它是否是一个Api调用。而'setApi'如果你想强制它成为一个API调用。有许多方法。但我会建议在你的情况下使用一个组件,因为你有一个非常好的观点,不会违反约定:)但是最终你会以if语句结束。因为你需要安全的JSON输出而不是html输出。 – Jelmer

+0

仍然不确定如何在登录表单返回为HTML之前跳入,并将正确的错误数据作为JSON传递。有没有办法将这个全局添加到JSON请求?检查Ajax调用并不是好的做法,因为我使用Ajax来处理其他事情,所以它会发生冲突。 – Cameron

2

希望这将这样的伎俩:

的代码片段一起使用命名参数与is('ajax')确定一个JSON请求,还检查如果用户没有登录,然后只发送一个。 JSON错误,如果请求的操作需要身份验证:

首先,把这个在您的beforeFilter()AppController

//see if request is json (json is sent by adding a named param e.g. posts/index/json:1 
//if so also check that user not already logged in 
if (!empty($this->params['named']['json']) && $this->request->is('ajax') && !$this->Auth->user()) 
{ 
    //see if the action needs authentication 
    $requiresAuth = !in_array($this->params['action'], $this->Auth->allowedActions); 
    if ($requiresAuth) 
    { 
     //send json response 
     $response = array('error' => 
      array(
       'code' => 123, 
       'message' => 'authError', 
      ) 
     ); 
     echo json_encode($response); 
     exit; 
    } 
} 

要请求JSON,将/json:1添加到您的路径(例如http://myserver.com/posts/index/json:1作为$ _GET参数)。 在每个控制器beforeFilter()中,请确保首先将允许的操作添加到$this->Auth->allow之前调用parent::beforeFilter()

如果使用的是与访问控制列表更高级的认证(ACL),见http://book.cakephp.org/2.0/en/core-libraries/components/access-control-lists.html,你还需要知道,如果动作是允许在ACL:

//the group_id to check permission for (must exist) 
$group_id = 8; //your group_id 
$group = array(
    'model' => 'Group', 
    'foreign_key' => $group_id 
); 
$actionPath = $this->name . '/' . $this->params['action']; 
$requiresAclAuth = $this->Acl->check($group, $actionPath); 

要查看是否需要进行身份验证ACL:

if ($requiresAclAuth && $requiresAuth) 
{ 
    //send json response 
    //... 
} 
相关问题