【问题标题】:Adding a XSRF-TOKEN via a HTTP Interceptor causes a 400 Bad Request通过 HTTP 拦截器添加 XSRF-TOKEN 会导致 400 错误请求
【发布时间】:2018-07-31 11:45:18
【问题描述】:

当我传递 JWT 时,使用 XSRF-TOKEN 防止 XSRF 攻击为我的 Angular 应用程序抛出了一个 cookie。这是我的HttpInterceptor 的样子。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headerName = "XSRF-TOKEN";
    const respHeaderName = "X-XSRF-TOKEN";
    let token = this.tokenExtractor.getToken() as string;
    if (token !== null && !req.headers.has(headerName)) {
        req = req.clone({ headers: req.headers.set(respHeaderName, token) });
    }
    return next.handle(req);
}

这会导致我的控制台中弹出 400 Bad Request 错误,并显示一条消息:预检响应没有 HTTP ok 状态。 如果我注释掉请求所在的代码行克隆后,错误消失,我的 HTTP 请求完美通过。

.htaccess 中的标题如下所示。

Header set Access-Control-Allow-Origin "http://localhost:4200"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Headers "Content-Type"
Header set Access-Control-Allow-Headers "Authorization"
Header set Access-Control-Allow-Headers "X-XSRF-TOKEN"
Header set Access-Control-Expose-Headers: "Authorization"

任何帮助将不胜感激,谢谢。

编辑 1:我的 PHP 代码的 MCVE

$return = array();

if (isset($_POST["email"]) && isset($_POST["password"])) {

    header("HTTP/1.0 200");
    $return["msg"] = "random";
    echo json_encode($return);

} else {

    header("HTTP/1.0 400");
    $return["error_message"] = "HTTP Post variables are not set!";
    $return["friendly_error_message"] = "Client error!";
    echo json_encode($return);

}

exit();

还有我的 Angular 服务中的 verify() 函数。

verify(email: string, password: string): Observable<JSON> {
    let headers = new HttpHeaders()
    headers = headers.set("Content-Type", "application/x-www-form-urlencoded");
    let body = new HttpParams();
    body = body.set("email", email);
    body = body.set("password", password);
    return this.http.post<JSON>("http://localhost:80/verify", body, { headers: headers, withCredentials: true, observe: "response" }).pipe(
        map(res => {
            return res.body;
        }),
        catchError(this.handleError)
    );
}

我一直在通过注释/取消注释一行 PHP 代码来测试“XSRF-TOKEN”会话 cookie。当会话 cookie 处于活动状态时,会发生此错误。

当我删除 cookie 时,我显然没有这个问题,因为 req.clone() 函数永远不会通过,因为条件不满足。

【问题讨论】:

  • 您还没有显示您的 PHP 代码。浏览器将对您的端点使用 OPTION 请求进行“预检”。它应该返回带有正确标题的“200 OK”响应。
  • 今天晚些时候我将编辑我的帖子并提交我的 PHP 代码。感谢您的帮助!
  • @KoalaYeung 查看我的编辑 :)
  • 当 (a) 它是一个 POST 请求时,您的 PHP 条件只会返回“200 OK”; (b) POST 正文具有正确的电子邮件和密码。正如我之前所说,预检请求始终是 OPTION 请求。因此,您的逻辑将始终返回“400 Bad Request”。
  • 这是有道理的,但我想我只是不明白为什么我正在做的整个“XSRF-TOKEN”事情会搞砸一切。

标签: php angular http-headers


【解决方案1】:

您的服务器端代码未正确响应 XSRF / CSRF 工作流程的预检请求。您必须对 OPTIONS 请求返回“200 OK”响应,这样您的 Angular 插件才能正常工作:

<?php

$return = array();

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {

    // instead of doing that in .htaccess
    header("Access-Control-Allow-Origin: http://localhost:4200");
    header("Access-Control-Allow-Credentials: true");
    header("Access-Control-Allow-Headers: Content-Type");
    header("Access-Control-Allow-Headers: Authorization");
    header("Access-Control-Allow-Headers: X-XSRF-TOKEN");
    header("Access-Control-Expose-Headers: Authorization");

    // a 200 OK response to preflight with empty body
    header("HTTP/1.0 200");

} elseif (isset($_POST["email"]) && isset($_POST["password"])) {

    // presuming all request that are not a preflight
    // must be a POST request.
    header("HTTP/1.0 200");
    $return["msg"] = "random";
    echo json_encode($return);

} else {

    header("HTTP/1.0 400");
    $return["error_message"] = "HTTP Post variables are not set!";
    $return["friendly_error_message"] = "Client error!";
    echo json_encode($return);

}

exit();

【讨论】:

  • 这行得通,但我不得不将所有标题语句移出第一个 if 块,因为我假设它抛出错误,当POST 请求命中时,因为没有Access-Control-Allow-Origin 响应头。不过感谢您的帮助!
猜你喜欢
  • 2019-06-29
  • 2022-01-21
  • 2019-11-12
  • 2018-11-03
  • 2019-07-06
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多