我不是经验丰富的后端开发人员,所以这个问题可能不是正确的问题,但问题是真实的!
我使用 Silex 作为 Angular 2 应用程序的简单后端,我有一个中间件来检查用户是否提供了 JWT 令牌。
$app->before(function (Request $request) use ($app) {
// Checks if the credential header is provided
if (!$token = $request->headers->get('X-BEARER-TOKEN')) {
return new Response('Bad Request', 400);
}
$data = $app['user.validateToken']($token); // This checks if the JWT token is valid
if(!$data || (int) $data['user_role_id'] != 2){
return new Response('Access Denied', 403);
}
});
我有一个 API 端点,它返回一些东西,比如说仪表板信息。
$app->get('/dashboard', function () use ($app) {
$stmnt = $app['db']->executeQuery(
"SELECT Query"
);
$result = $stmnt->fetchAll();
if($result === false) {
return new Response('Not Found', 404);
}else{
$result = array('message' => 'success', 'status' => 200, 'data' => $result);
return $app->json($result, 200);
}
});
这不起作用,我收到“错误请求”,因为请求无法获取标头数据。
令人费解的注释: A - 如果我从 Postman 调用 API,上面的代码运行良好,但是当我从浏览器(在本例中是 Angular 应用程序)调用 API 时,我收到错误请求。
B - 如果我将凭证逻辑从中间件之前移动到端点(下面的代码),Postman 调用和应用程序调用一切正常。
$app->get('/dashboard', function (Request $request) use ($app) {
// Checks if the credential header is provided
if (!$token = $request->headers->get('X-BEARER-TOKEN')) {
return new Response('Bad Request', 400);
}
$data = $app['user.validateToken']($token);
if(!$data || (int) $data['user_role_id'] != 2){
return new Response('Access Denied', 403);
}
$stmnt = $app['db']->executeQuery(
"SELECT Query"
);
$result = $stmnt->fetchAll();
if($result === false) {
return new Response('Not Found', 404);
}else{
$result = array_map('intval', $result[0]);
$result = array('message' => 'success', 'status' => 200, 'data' => $result);
return $app->json($result, 200);
}
});
知道我错过了什么吗?
顺便说一句,为了使预检 CORS 选项正常工作,我在应用程序末尾附加了以下代码,我不确定它是否与问题相关。
$app->match("{url}", function($url) use ($app){
return "OK";
})->assert('url', '.*')->method("OPTIONS");
好吧,我发现了这个问题,这很愚蠢,IMO,
问题是没有正确考虑应用程序生命周期, $app->before 在 $app->options 之前运行,因此当浏览器询问 OPTIONS 标头是否可接受时,->before 生命周期不知道如何处理它。
在解决问题之前添加以下代码到->:
if ($request->getMethod() == 'OPTIONS') {
return new Response(null, 204);
}
当然,这会导致 ->options 和 ->match 过时,这仍然很时髦。也许我所做的只是一种解决方法,而不是解决方案。