javascript - OPTIONS 请求得到 "401 Unauthorized"响应

标签 javascript jquery api cors symfony4

我使用 Symfony 4 制作了一个使用自定义 token 验证的 API。我在 Postman 上测试了 API,一切正常,现在我想使用 jQuery 使用 API 并获取所有数据,但在浏览器中,我面临如下所示的 CORS 问题:

Access to XMLHttpRequest at 'http://localhost:8000/api/reports' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

这是我的服务器端 API:

我已经实现了 CORSEventSubscriber允许如下所示的 CORS:

class CORSSubscriber implements EventSubscriberInterface
{

/**
 * @var TokenStorageInterface
 */
private $tokenStorage;

public function __construct(TokenStorageInterface $tokenStorage)
{
    $this->tokenStorage = $tokenStorage;
}
public function onKernelResponse(FilterResponseEvent $event)
{
    $responseHeaders = $event->getResponse()->headers;
    $responseHeaders->set('Access-Control-Allow-Origin', '*');
    $responseHeaders->set('Access-Control-Allow-Headers', 'x-auth-token, content-type');
    $responseHeaders->set('Access-Control-Allow-Methods', 'POST, GET');
}

/**
 * @inheritDoc
 */
public static function getSubscribedEvents()
{
    return [
        KernelEvents::RESPONSE => 'onKernelResponse',
    ];
}

这是我在 Controller 中调用的操作:

/**
 * @Route("/api/reports",name="reports",methods={"GET","OPTIONS"})
 * @param Request $request
 * @return Response
 * @throws  Exception
 */
function getReports(Request $request){

return new JsonResponse('test', Response::HTTP_UNAUTHORIZED);

}

我尝试使用 API像这样

    <script>
    $(document).ready(function(){

        authenticate().then(function (data) {
           // the promise resolve the token and data.token output the correct value
           $.ajax({
               url:'http://localhost:8000/api/reports',
               type: 'GET',
                headers: {'X-Auth-Token' : data.token },
               success: function (data) {
                   //append data to your app
                   console.log(data);
               }
           })
        })
    });
    function authenticate() {
        let data={
            "username": "test",
            "password": "test"
        };
        return new Promise(function(resolve, reject) {
            $.ajax({
                url:'http://localhost:8000/api/auth/check',
                type:'POST',
                data:JSON.stringify(data),
                dataType:'Json',
                success: function (data) {
                    console.log(data);
                resolve(data);
                },
                error:function () {
                }
            })
        });
    }


</script>

我添加这个是为了仔细调试问题,我发现这个函数只针对 POST 执行。当有像 OPTIONS 这样的 token 方法时它不执行

public function onKernelRequest(GetResponseEvent $event)
{
    $this->logger->info($event->getRequest()->getRealMethod());
}

最佳答案

您正在发出跨源请求并添加非标准 header 。这意味着它是 Preflighted Request

浏览器正在发送 OPTIONS 请求,以请求使用自定义 header 发出请求的权限。

您无法控制预检请求的格式。您绝对不能向其中添加凭据。 (添加凭据是将简单请求转变为预检请求的另一件事)。

您需要通过 CORS header 响应具有权限的 OPTIONS 请求。由于请求不会有任何与之关联的凭据,因此您的服务器一定不需要凭据

更改服务器以删除请求类型为 OPTIONS 时对凭据的要求。

<小时/>

我不知道您正在使用的服务器端框架的方式,但从您提供的代码推断,我怀疑您应该为 GET 和 OPTIONS 提供单独的路由

OPTIONS 请求应该只关注 CORS(而不获取任何需要授权的数据)。

GET 请求应该需要授权并返回数据。

关于javascript - OPTIONS 请求得到 "401 Unauthorized"响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59681742/

相关文章:

javascript - 修复 ASP.NET GridView 的标题行

javascript - 如何使用网络音频 API/javascript 操作 DOM?

api - 如何设计 RESTful 高级搜索/过滤器

javascript - BlueImp Gallery - 如何停用滑动事件

javascript - 如何跳转到不同 fullpage.js 滚动部分之间的 #id anchor ?

jquery - 使用 Jquery 粗体表行

javascript - 从 Python (Flask) 传递到 JavaScript 的 JSON 显示在屏幕上

javascript - 无法将状态值插入对象

javascript - 按钮或隐藏文件的 html 验证

python - 我可以从 CCXT API 调用获得原始交换响应吗?