Yii2:如何在非restfull API上允许CORS

ech*_*lik 5 javascript ajax jquery cors yii2

我正在使用Yii2 Framework上的预构建API(而不是restfull).它响应JSON数据并接受取决于用户类型和凭证令牌的请求.现在我必须创建一个位于不同位置(域)的应用程序,这会导致CORS冲突.

我的应用程序是jQuery,我$.ajax用于数据发送和接收.如何避免此CORS冲突并使用API​​而不是ajax?

问候

更新:

正如IStranger在回答中告诉我的那样,我添加了以下代码:

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
        'cors' => [
            'Origin'                           => "*",
            'Access-Control-Request-Method'    => ['POST', 'GET'],
            'Access-Control-Allow-Credentials' => true,
            'Access-Control-Max-Age'           => 3600,
        ],
    ];
    return $behaviors;
}
Run Code Online (Sandbox Code Playgroud)

但我仍然得到错误.有一个beforeAction在代码中可以说是一个问题?

这是RAW HEADER

请求:

Host: domain.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost/main/main.html
Content-Length: 296
Origin: http://localhost
Connection: keep-alive
Run Code Online (Sandbox Code Playgroud)

响应:

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Content-Length: 101
Content-Type: application/json; charset=UTF-8
Date: Thu, 22 Sep 2016 17:23:48 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache/2.4.17 (Win64) PHP/5.6.16
Set-Cookie: PHPSESSID=ph0b322gbq65m1f3m8fp9fphc0; path=/; HttpOnly
X-Powered-By: PHP/5.6.16
Run Code Online (Sandbox Code Playgroud)

ISt*_*ger 8

只需添加到您的API控制器:

/**
 * 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)
            ],
        ],

    ]);
}
Run Code Online (Sandbox Code Playgroud)

此代码将添加到响应特殊的http-headers.请求http标头应该有Origin(它将由浏览器自动添加到Crossdomain AJAX).响应http标头应该有Access-Control-*标头.

注意:如果您没有看到这些http标头作为响应,可能意味着它\yii\filters\Cors不起作用.检查控制器中的其他行为/过滤器.尝试禁用此控制器的CSRF验证(可能会阻止外部访问):

/**
 * Controller for API methods.
 */
class ApiController extends Controller
{

    /**
     * @var bool See details {@link \yii\web\Controller::$enableCsrfValidation}.
     */
    public $enableCsrfValidation = false;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

UPD:另外应检查您的网络服务器.可能nginx可能需要额外配置,apache可能需要重启.

UPD2:更完整的说明:https://stackoverflow.com/a/42435695/3793592