Following This question i have set my rest controller behaviour as
public function behaviors()
{
$behaviors = parent::behaviors();
$auth= $behaviors
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
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']
In case of any problems with CORS headers, I recommend to use following instruction:
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)
],
],
]);
}
The above code will add to response special http-headers. Check http-headers using browser debug tools:
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
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
If you don't see these http headers in response, probably it means that \yii\filters\Cors
doesn't work or conflicts with other filters.
Check other behaviors/filters in controller. Try add corsFilter
as first behavior. Probably some other behaviors prevents execution of corsFilter
.
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;
// ...
}
If you are using authenticator filter (for example, your controller extends yii\rest\ActiveController
) the CORS filter has to be applied BEFORE authentication methods. Also authentication has to be disabled for the CORS Preflight requests so that a browser can safely determine whether a request can be made beforehand without the need for sending authentication credentials.
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::className(),
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
Additionally should be checked your web-server. Probably nginx may require additional configuration, apache can require restarting.
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.
Some useful information can be found here:
It is important to write $behaviors['access'] ie. AccessControl as a last parameter, for example:
public function behaviors() {
$behaviors = parent::behaviors();
// remove authentication filter
unset($behaviors['authenticator']);
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::class,
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['POST', 'GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Allow-Headers' => ['Origin', 'X-Requested-With', 'Content-Type', 'accept', 'Authorization'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Max-Age' => 3600, // Cache (seconds)
// Allow the X-Pagination-Current-Page header to be exposed to the browser.
'Access-Control-Expose-Headers' => ['X-Pagination-Total-Count', 'X-Pagination-Page-Count', 'X-Pagination-Current-Page', 'X-Pagination-Per-Page']
]
];
$behaviors['authenticator'] = [ ... whatever ... ];
$behaviors['access'] = [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['options'], // important for cors ie. pre-flight requests
],
]
];
}