Yii2 cors filters error that No 'Access-Control-Allow-Origin' header is present

你说的曾经没有我的故事 提交于 2019-11-30 22:05:18

问题


Following This question i have set my rest controller behaviour as

public function behaviors()
{
    $behaviors = parent::behaviors();

    $auth= $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'only' => ['dashboard'],
    ];
    $behaviors['contentNegotiator'] = [
        'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
    ];
    $acces=$behaviors['access'] = [
        'class' => AccessControl::className(),
        'only' => ['login'],
        'rules' => [
            [
                'actions' => ['login'],
                'allow' => true,
                'roles' => ['?'],
            ],
        ],
    ];

    unset($behaviors['authenticator']);
    unset($behaviors['access']);

And now the cors filters

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
          'cors' => [
        // restrict access to
        'Access-Control-Allow-Origin' => ['*'],
        'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
        // Allow only POST and PUT methods
        'Access-Control-Request-Headers' => ['*'],
        // Allow only headers 'X-Wsse'
        'Access-Control-Allow-Credentials' => true,
        // Allow OPTIONS caching
        'Access-Control-Max-Age' => 86400,
        // Allow the X-Pagination-Current-Page header to be exposed to the browser.
        'Access-Control-Expose-Headers' => [],
      ]
    ];

    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
       $behaviors['access'] = $access;
    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];
    return $behaviors;
}

An my angular2 frontend as

    const body = JSON.stringify(user);
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Content-Type', 'application/json');
headers.append('Access-Control-Allow-Credentials', "*");
return this._http.post(this.loginUrl, body, { headers:headers })
  .map((response: Response) => {
     //process response
  })
.catch(this.handleError);

But am still getting an error of

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:3000' is therefore not allowed access.

What could be wrong since ive set the cors filter in yii2 behaviours unset authenticator and added it later What could i be missing out

I have also checked on This link and also this one but none solves the issue


回答1:


In case of any problems with CORS headers, I recommend to use following instruction:

  1. Add cors configuration to your controller. For instance:

    /**
     * List of allowed domains.
     * Note: Restriction works only for AJAX (using CORS, is not secure).
     *
     * @return array List of domains, that can access to this API
     */
    public static function allowedDomains() {
        return [
            // '*',                        // star allows all domains
            'http://test1.example.com',
            'http://test2.example.com',
        ];
    }
    
    /**
     * @inheritdoc
     */
    public function behaviors() {
        return array_merge(parent::behaviors(), [
    
            // For cross-domain AJAX request
            'corsFilter'  => [
                'class' => \yii\filters\Cors::className(),
                'cors'  => [
                    // restrict access to domains:
                    'Origin'                           => static::allowedDomains(),
                    'Access-Control-Request-Method'    => ['POST'],
                    'Access-Control-Allow-Credentials' => true,
                    'Access-Control-Max-Age'           => 3600,                 // Cache (seconds)
                ],
            ],
    
        ]);
    }
    
  2. The above code will add to response special http-headers. Check http-headers using browser debug tools:

  3. Request http header should contain Origin. It will be added by browser automatically at Crossdomain AJAX. This http-header can be added also via your JS library. Without this http-header corsFilter won't work.

    POST /api/some-method-name HTTP/1.1
    Host: api.example.com
    Connection: keep-alive
    Content-Length: 86
    Accept: */*
    Origin: https://my-site.example.com
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Referer: https://my-site.example.com/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,ru;q=0.4
    
  4. Response http headers should contain Access-Control-* headers. This http-header will be added by corsFilter.

    HTTP/1.1 200 OK
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: https://my-site.example.com
    Content-Type: application/json; charset=UTF-8
    Date: Fri, 24 Feb 2017 09:21:47 GMT
    Server: Apache
    Content-Length: 27
    Connection: keep-alive
    
  5. If you don't see these http headers in response, probably it means that \yii\filters\Cors doesn't work.

  6. Check other behaviors/filters in controller. Try add corsFilter as first behavior. Probably some other behaviors prevents execution of corsFilter.

  7. Try to disable CSRF validation for this controller (it may prevent external access):

    /**
     * Controller for API methods.
     */
    class ApiController extends Controller
    {
    
        /**
         * @var bool See details {@link \yii\web\Controller::$enableCsrfValidation}.
         */
        public $enableCsrfValidation = false;
    
        // ...
    }
    
  8. Additionally should be checked your web-server. Probably nginx may require additional configuration, apache can require restarting.

  9. Access-Control-* headers in response can be added using web-server (see for apache and nginx). But I don't recommend to use this way, because in this case you can't manage http-haders using application.

  10. Some useful information can be found here:

    • Yii2: How to allow CORS on non-restfull API



回答2:


Try This :

public static function allowedDomains()
{
    return [
        // '*',                        // star allows all domains
        'http://localhost:3000',
        'http://test2.example.com',
    ];
}  



public function behaviors()
    {
        return array_merge(parent::behaviors(), [

            // For cross-domain AJAX request
            'corsFilter'  => [
                'class' => \yii\filters\Cors::className(),
                'cors'  => [
                    // restrict access to domains:
                    'Origin'                           => static::allowedDomains(),
                    'Access-Control-Request-Method'    => ['POST'],
                    'Access-Control-Allow-Credentials' => true,
                    'Access-Control-Max-Age'           => 3600,                 // Cache (seconds)

                ],
            ],

        ]);
    }

Add This Function on your controller .

And One Thing angular2 use OPTION method at the first time For so allow OPTION method also




回答3:


The problem arises when the frontend runs in a port other than the default port (80).

Then in yii you need to specify the port to work. Example: frontend runs at http: // localhost: 3000 in Yii cors set:

'Origin' => ['http: // localhost: 3000']

If you do not specify the port (3000), Yii interprets the port by default and the result is:

'Origin' => ['http: // localhost: 80']


来源:https://stackoverflow.com/questions/41647444/yii2-cors-filters-error-that-no-access-control-allow-origin-header-is-present

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!