API 服务器总是响应“否 'Access-Control-Allow-Origin'”

API Server always response " No 'Access-Control-Allow-Origin'"

我用laravel写后端。并尝试从 IONIC 使用 @angular/http.

调用 api

在后端服务器中,我已经在中间件和响应中添加了Access-Control-Allow-Origin

中间件。

return $next($request)
      ->header('Access-Control-Allow-Origin', '*')
      ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
      ->header('Access-Control-Allow-Credentials', true)
      ->header('Access-Control-Allow-Headers', 'Content-Type')
      ->header('Vary', 'Origin');

响应。

return response($data, 200)
      ->withHeaders([
        'Content-Type' => 'application/json',
        'Access-Control-Allow-Origin' => '*',
        'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE',
        'Access-Control-Allow-Credentials' => true,
        'Access-Control-Allow-Headers' => 'Content-Type',
        'Vary' => 'Origin',
      ]);

离子

  url: any = 'http://myurl.local/api/';

  headers = new Headers(
  {
    'Accept' : 'application/json',
    'Content-Type' : 'application/json',
    'Access-Control-Request-Methods' : 'POST'
  });
  options = new RequestOptions({ headers: this.headers });

login(username, password) {
    let data = JSON.stringify({
      username : username,
      password : password
    });
    let fullUrl = this.url+'login';

    return new Promise((resolve, reject) => {
      this.http.post(fullUrl, data, this.options)
      .toPromise()
      .then((response) =>
      {
        console.log('API Response : ', response);
        resolve(response.json());
      })
      .catch((error) =>
      {
        console.error('API Error : ', error.toString());
        reject(error.json());
      });
    });
  }

当我用 'Content-Type' : 'application/json' 调用 api 时,它总是响应错误。

XMLHttpRequest cannot load http://myurl.local/api/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.

但是如果我把'Content-Type'改成'application/x-www-form-urlencoded'。我没有收到任何错误。

但是当我尝试查看输入时 $request->all()。我得到的数据是 '{"username":"XXXXXXXXXX","password":"XXXXXXXXXX"}' => NULL.

用邮递员就可以了。我真的尝试了很多方法来解决这个问题,但我不能。

怎么了?

在处理请求的 Laravel 代码中,您需要添加对 OPTIONS 请求的处理:

if ($request->getMethod() == "OPTIONS") {
    $headers = [
        'Access-Control-Allow-Origin' => '*'
        'Access-Control-Allow-Methods'=> 'POST, GET',
        'Access-Control-Allow-Headers'=> 'Content-Type'
    ];
    return Response::make('OK', 200, $headers);
}

When I call api with 'Content-Type' : 'application/json' it always response error.

But if I change 'Content-Type' to 'application/x-www-form-urlencoded'. I didn't get any errors.

application/json 内容类型触发浏览器执行 CORS 预检 OPTIONS 请求。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests 有更多详细信息。

With postman is fine.

Postman可以不受限制的自由跨域请求。但是浏览器将不允许您的前端 JavaScript 代码访问来自跨域请求的响应,除非该响应表明发送请求的服务器正在选择接收跨域请求。

如果您的请求触发浏览器执行 CORS 预检 OPTIONS 请求,则发送请求的服务器必须配置为以正确的方式响应 OPTIONS 请求.这就是为什么您需要在 Laravel 代码中为 OPTIONS 请求添加额外的处理。

如果服务器没有以正确的方式响应 OPTIONS 预检,浏览器将停在那里,永远不会处理您实际尝试发送的 POST 请求.

啊啊啊!!!最后,我可以解决这个问题。该死的。

在中间件中。

public function handle($request, Closure $next)
  {
    if ($request->getMethod() == "OPTIONS") {
      return response(['OK'], 200)
        ->withHeaders([
          'Access-Control-Allow-Origin' => '*',
          'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE',
          'Access-Control-Allow-Credentials' => true,
          'Access-Control-Allow-Headers' => 'Authorization, Content-Type',
        ]);
    }

    return $next($request)
    ->header('Access-Control-Allow-Origin', '*')
    ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
    ->header('Access-Control-Allow-Credentials', true)
    ->header('Access-Control-Allow-Headers', 'Authorization, Content-Type');

  }

在 IONIC 中将 header 更改为。

headers = new Headers(
{
  'Content-Type' : 'application/json'
});

并且在您添加 options 路由之前它不会工作。 (就我而言,因为我没有使用 Route::resource

Route::group(['middleware' => 'AddHeader'], function()
{
  Route::post('/login', 'LoginController@index');
  Route::options('/login', 'LoginController@index');
});

PS。我在function index()中有一些逻辑,我尝试使用__construct()。但是不行。