如何在 Cakephp 4 中正确抛出 UnauthenticatedException?
How to correctly throw an UnauthenticatedException in Cakephp 4?
我在 cakephp 4 中使用插件 Authentication 2。
我想在用户未登录和 ajax 请求的情况下抛出 UnauthenticatedException
。
目标是捕获 JSON 中的异常。
这是我来自服务器的代码:
// in src/Controller/Admin/AdminController.php
use Authentication\Authenticator\UnauthenticatedException;
class AdminController extends AppController {
public function initialize(): void
{
parent::initialize();
$this->loadComponent('Authentication.Authentication');
}
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
// The server receives an ajax request and the user is not logged in (any more), an UnauthenticatedException is thrown
if ($this->request->is('ajax') && $this->request->getAttribute('identity') === null) {
throw new UnauthenticatedException('Please log in');
}
}
}
这是我从客户那里得到的代码:
$.ajax({
dataType: 'json';
type: 'POST',
data: $(form).serialize(),
// [...]
})
// [...]
.fail(function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.responseJSON); // There's no responseJSON in jqXHR...
alert("(" + errorThrown + ")" + jqXHR.responseJSON.message);
if (errorThrown == 'Unauthenticated') {
location.reload();
}
});
问题是 jqXHR
中没有 responseJSON
。
为什么任何其他异常(例如我之前使用的 UnauthorizedException
)在 return 中生成 responseJSON
而不是 UnauthenticatedException
?
如何让它与 UnauthenticatedException
一起工作?
身份验证中间件默认re-throws未经身份验证的异常,即除非您配置unauthenticatedRedirect
选项,否则它将相应地将这些异常转换为重定向。
如果需要同时支持HTML和JSONrequests/responses,那么可以比如动态配置,分别不配置unauthenticatedRedirect
选项,基于当前请求,例如在您的 Application::getAuthenticationService()
方法中执行以下操作:
$service = new AuthenticationService();
$accepts = array_map('trim', explode(',', $request->getHeaderLine('Accept')));
$isJsonRequest = in_array('application/json', $accepts, true);
if (!$isJsonRequest) {
// service config for non-JSON requests
$service->setConfig([
'unauthenticatedRedirect' => /* ...*/,
'queryParam' => 'redirect',
]);
}
或者手动评估 header,要求 request
成为 \Cake\Http\ServerRequest
的实例并使用它的 is()
方法:
assert($request instanceof \Cake\Http\ServerRequest);
if (!$request->is('json')) {
$service->setConfig([
'unauthenticatedRedirect' => [/* ...*/],
'queryParam' => 'redirect',
]);
}
另请注意,身份验证组件默认要求提供身份并相应地抛出异常,您不必自己执行此操作。
我在 cakephp 4 中使用插件 Authentication 2。
我想在用户未登录和 ajax 请求的情况下抛出 UnauthenticatedException
。
目标是捕获 JSON 中的异常。
这是我来自服务器的代码:
// in src/Controller/Admin/AdminController.php
use Authentication\Authenticator\UnauthenticatedException;
class AdminController extends AppController {
public function initialize(): void
{
parent::initialize();
$this->loadComponent('Authentication.Authentication');
}
public function beforeFilter(EventInterface $event)
{
parent::beforeFilter($event);
// The server receives an ajax request and the user is not logged in (any more), an UnauthenticatedException is thrown
if ($this->request->is('ajax') && $this->request->getAttribute('identity') === null) {
throw new UnauthenticatedException('Please log in');
}
}
}
这是我从客户那里得到的代码:
$.ajax({
dataType: 'json';
type: 'POST',
data: $(form).serialize(),
// [...]
})
// [...]
.fail(function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.responseJSON); // There's no responseJSON in jqXHR...
alert("(" + errorThrown + ")" + jqXHR.responseJSON.message);
if (errorThrown == 'Unauthenticated') {
location.reload();
}
});
问题是 jqXHR
中没有 responseJSON
。
为什么任何其他异常(例如我之前使用的 UnauthorizedException
)在 return 中生成 responseJSON
而不是 UnauthenticatedException
?
如何让它与 UnauthenticatedException
一起工作?
身份验证中间件默认re-throws未经身份验证的异常,即除非您配置unauthenticatedRedirect
选项,否则它将相应地将这些异常转换为重定向。
如果需要同时支持HTML和JSONrequests/responses,那么可以比如动态配置,分别不配置unauthenticatedRedirect
选项,基于当前请求,例如在您的 Application::getAuthenticationService()
方法中执行以下操作:
$service = new AuthenticationService();
$accepts = array_map('trim', explode(',', $request->getHeaderLine('Accept')));
$isJsonRequest = in_array('application/json', $accepts, true);
if (!$isJsonRequest) {
// service config for non-JSON requests
$service->setConfig([
'unauthenticatedRedirect' => /* ...*/,
'queryParam' => 'redirect',
]);
}
或者手动评估 header,要求 request
成为 \Cake\Http\ServerRequest
的实例并使用它的 is()
方法:
assert($request instanceof \Cake\Http\ServerRequest);
if (!$request->is('json')) {
$service->setConfig([
'unauthenticatedRedirect' => [/* ...*/],
'queryParam' => 'redirect',
]);
}
另请注意,身份验证组件默认要求提供身份并相应地抛出异常,您不必自己执行此操作。