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

走远了吗. 提交于 2019-12-01 03:04:39
IStranger

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:

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

Dino Di Luca

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