我正在尝试使用完全用jQuery编写的应用程序在CakePHP中实现基本身份验证。我打算使用OAuth2,但厌倦了增加的复杂性,因为这个应用程序将是唯一使用API的东西,Basic Auth就足够了。
登录方法如下:
login: function(username, password) {
$.ajax({
type: 'GET',
url: 'http://api.domain.com/login',
beforeSend : function(xhr) {
var base64 = $.base64.encode(username + ':' + password);
xhr.setRequestHeader("Authorization", "Basic " + base64);
},
dataType: 'jsonp',
success: function(data) {
if( data.response.status == 'error' ) {
alert(data.response.message);
} else {
// Save some sort of session
}
},
error: function(a,b,c) {
console.log(a,b,c);
}
});
}
在CakePHP方面:
public function login() {
if ($this->request->is('get')) {
if ($this->Auth->login()) {
$response = json_encode(
array(
'meta'=>array(
'code'=>$this->response->statusCode(),
'in'=>round(microtime(true) - TIME_START, 4)
),
'response'=>array(
'status'=>'success',
'message'=>'successfully logged in'
)
)
);
} else {
$response = json_encode(
array(
'meta'=>array(
'code'=>$this->response->statusCode(),
'in'=>round(microtime(true) - TIME_START, 4)
),
'response'=>array(
'status'=>'error',
'message'=>'incorrect login details'
)
)
);
}
// Handle JSONP
if(isset($_GET['callback'])) {
$response = $_GET['callback'] . '(' . $response . ')';
}
// Return JSON
$this->autoRender = false;
$this->response->type('json');
$this->response->body($response);
}
}
更新: 在对此进行了一些研究之后,我发现用户名和密码需要随每个请求发送...所以实际上不会有会话或cookie。但我需要将这些信息存储在某个地方?否则,用户将在页面上的每个请求后登录?
用户登录后立即进行身份验证...如何对数据发出请求并处理身份验证以确保正确的用户具有访问权限,以及他们是否创建了以此身份创建的数据。就像在OAuth2中一样,我会有一个access_token我可以传递给访问数据,但在Basic Auth中,你没有令牌。并且由于没有会话,我无法访问登录的用户信息。那我该怎么做呢?
根据CakePHP文档,你不需要在CakePHP 2.4+中使用登录方法(对于Basic Auth),那么用户如何从客户端登录以及在通过时我将与之交谈哪种控制器方法用户名和密码?
更新:当我尝试根据上面的代码访问登录方法时,我会收到用户名和密码的提示......但这是允许的方法!有什么想法吗?因为它阻止我的JavaScript发送请求,因为永远无法访问端点。此外,如果我使用提示登录,即使我访问注销方法或清除浏览器中的所有会话/缓存,我仍然已登录。那么如何删除用户登录?
非常感谢任何指导我正确方向的帮助,因为我觉得我完全误解了Basic Auth的工作方式......有些例子会很棒!
更新2:
根据PHP文档,以下是检查用户是否登录的方法,如果取消则显示消息。该信息也存储在没有任何会话使用的情况下!那么同样的原理如何适用于CakePHP?例如,如何显示正确的401状态和自定义消息,如果基于此状态,如何将记录的用户信息存储在CakePHP中?
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>
答案 0 :(得分:3)
虽然基本身份验证是无状态的,但根据CakePHP文档:
使用基本身份验证的客户端必须支持Cookie。以来 AuthComponent根据会话内容,客户端识别用户 使用Basic Auth必须支持cookie。
http://api.cakephp.org/2.5/class-BasicAuthenticate.html
可是:
您也可以将
AuthComponent::$sessionKey
设置为false以确保 AuthComponent不会尝试从会话中读取用户信息。无状态 身份验证将在每个请求上重新验证用户的凭据, 这会产生少量的额外开销,但允许客户端 不使用cookies登录。
你的AppController应该是这样的:
class AppController extends Controller {
public $components = array('Auth', 'Session');
public function beforeFilter() {
$this->Auth->authorize = array('Controller');
$this->Auth->authenticate = array('Basic');
$this->Auth->sessionKey = false;
}
}
您可能还想使用$this->Auth->unauthorizedRedirect = false;
。默认情况下,未经授权的用户被重定向到引用者URL或AuthComponent :: $ loginAction或‘/’
。如果unauthorizedRedirect
设置为false
,则抛出ForbiddenException异常而不是重定向。
然后在每个控制器中,您必须使用isAuthorized()
方法,根据其角色授权用户,方法与通常的表单身份验证相同。 F.ex:
public function isAuthorized($user) {
if (isset($user['role']) && ($user['role'] == 'admin')) {
return true;
}
return false;
}
因为基本身份验证和摘要身份验证不需要初始POST 或表格,如果只使用基本/摘要验证器,则不需要 需要在控制器中执行登录操作。
这意味着您无需显式调用Users :: login(),当用户尝试访问URL时,将显示“基本身份验证”窗口,如果不这样,每次请求页面时都必须输入用户名和密码像在Ajax调用xhr.setRequestHeader("Authorization", "Basic " + base64);
中一样发送基本授权标头。
如果不希望每个请求都向用户显示这样一个窗口,您可以将用户凭据存储在cookie中,或者最好存储在客户端的本地存储(http://www.w3schools.com/html/html5_webstorage.asp)中,并设置“授权”头每个请求(对任何控制器的任何动作)。
您始终可以通过以下方式将经过身份验证的用户详细信息从控制器发送回客户端:
$this->set(array(
'user' => json_encode($this->Auth->user()),
'_serialize' => array('user')
));
您可以从beforeFilter()
执行此操作,以便在每次回复时发送经过身份验证的用户详细信息。
答案 1 :(得分:1)
可以在没有cookie的情况下使用会话,在每个查询中将其作为参数共享,并作为json响应的值。
准备应用程序以在database or cache
成功登录ajax后,在json响应中包含sessionID
每个下一个请求必须包含sessionID作为参数,响应还必须包含sessionID
我就是这样做的。