无法在Slim Framework中覆盖CORS标头

时间:2018-12-03 02:32:03

标签: php cors slim-3

我正在将Slim v3与https://github.com/tuupola/cors-middleware处的CORS中间件一起使用来处理CORS标头。一切正常,但是我现在需要能够根据用户登录身份来修改Access-Control-Allow-Origin标头。我有另一个在CORS中间件之后执行的中间件来进行用户验证,我希望从这个中间件中我可以添加$ response = $ response-> withHeader('Access-Control-Allow-Origin',$ userdomain)并且它将保留由先前的中间件设置的其余CORS标头,但覆盖该中间件。但是,这似乎没有发生。无论此中间件在哪里执行,CORS标头始终是CORS中间件定义的标头。

当前设置如下:

$app->add(new \Internal\OAuth\Middleware($this->getDBs()));

$app->add(new \Tuupola\Middleware\Cors([
    "origin" => ['*'],
    "methods" => ['GET', 'POST', 'PUT', 'OPTIONS', 'DELETE'],
    "headers.allow" => ['', 'Authorization', 'Content-Type', 'Content-Length', 'Origin', 'Accept'],
    "credentials" => true,
    "cache" => 100
]));

\ Internal \ OAuth \ Middleware __invoke看起来像这样:

public function __invoke($req, $res, $next) {
    //do authentication stuff
    $userdomain = 'http://blahblahblah';
    $res = $res->withHeader('Access-Control-Allow-Origin', $userdomain);
    return $next($req, $res);
}

2 个答案:

答案 0 :(得分:2)

在中间件中,您需要在处理程序之后添加标头

<?php

namespase \Internal\OAuth;

class Middleware
{
    public function __invoke($req, $res, $next) {
        //do authentication stuff
        $userdomain = 'http://blahblahblah';
        $res = $next($req, $res);
        return $res->withHeader('Access-Control-Allow-Origin', $userdomain);
    }
}

答案 1 :(得分:0)

尝试一下:

index.php

<?php

$app = new \Slim\App();

$app->add(new \Internal\OAuth\Middleware());

$app->get('/', function(\Psr\Http\Message\ServerRequestInterface $req, \Psr\Http\Message\ResponseInterface $res, $args) {
    $res->getBody()->write(json_encode(['url' => $req->getUri()->__toString(), 'args'=>$args]));
    return $res->withHeader('content-type', 'application/json');
});

$app->run();

src/Internal/OAuth/Middleware.php

<?php

namespace Internal\OAuth;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class Middleware
{

    /**
     * @param ServerRequestInterface $req
     * @param ResponseInterface $res
     * @param callable $next
     * @return ResponseInterface
     */
    public function __invoke($req, $res, $next) {
        //do authentication stuff
        $options = [
            "origin" => ['http://blahblahblah'],
            "methods" => ['GET', 'POST', 'PUT', 'OPTIONS', 'DELETE'],
            "headers.allow" => ['', 'Authorization', 'Content-Type', 'Content-Length', 'Origin', 'Accept'],
            "credentials" => true,
            "cache" => 100
        ];
        $cors = new \Tuupola\Middleware\CorsMiddleware($options);
        $handler = new Handler($res, $next);
        $res = $cors->process($req, $handler);
        return $res;
    }
}

src/Internal/OAuth/Handler.php

<?php

namespace Internal\OAuth;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class Handler implements RequestHandlerInterface
{

    protected $callable;

    protected $response;

    public function __construct(ResponseInterface $response, callable $callable)
    {
        $this->callable = $callable;
        $this->response = $response;
    }

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $handler = $this->callable;
        return $handler($request, $this->response);
    }
}

测试:

1。

curl "http://localhost:8088" --request OPTIONS --include --header "Origin: http://disallowed-host" --header "Access-Control-Request-Method: PUT"

HTTP/1.1 401 Unauthorized
Host: localhost:8088
Date: Tue, 04 Dec 2018 13:19:14 +0700
Connection: close
Content-Length: 0

2。

curl "http://localhost:8088" --request OPTIONS --include --header "Origin: http://blahblahblah" --header "Access-Control-Request-Method: PUT"

HTTP/1.1 200 OK
Host: localhost:8088
Date: Tue, 04 Dec 2018 13:19:04 +0700
Connection: close
Access-Control-Allow-Origin: http://blahblahblah
Access-Control-Allow-Credentials: true
Vary: Origin
Access-Control-Max-Age: 100
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE
Content-Length: 0