通过HTTP拦截器添加XSRF-TOKEN会导致400错误请求

时间:2018-07-30 06:21:46

标签: php angular http-headers

当我通过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正常状态。如果我注释掉请求所在的代码行克隆,错误消失,我的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:我的MCVE PHP代码

$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处于活动状态时,会发生此错误。

console

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

1 个答案:

答案 0 :(得分: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();