Issue in adding Xsrf-Token in an Angular 6

我怕爱的太早我们不能终老 提交于 2019-12-07 19:19:43

问题


Posting data from the form submit via API was successful.

But after adding X-CSRF-TOKEN to the header and setting withCredentials: true resulted data were not posted to the script named insert.php

Error:

Failed to load http://localhost/simple_api/insert.php: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Removing withCredentials: true resulted data were successfully posted. But unable to see the X-CSRF-TOKEN

app.module.ts

import { HttpModule } from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";
import { UsrService } from './usr.service';
import { AppComponent } from './app.component';

@NgModule({
    declarations: [
      AppComponent,
      RegisterComponent,
      LoginComponent
    ],
    imports: [
      BrowserModule,
      FormsModule,
      HttpModule,
      AppRoutingModule,
      HttpClientModule,
      HttpClientXsrfModule.withOptions({
        cookieName: 'XSRF-TOKEN',
        headerName: 'X-CSRF-TOKEN'
      })
    ],
    providers: [UsrService],
    bootstrap: [AppComponent]
  })
  export class AppModule { }

user.services.ts

import { Http, Headers, RequestOptions, Response, URLSearchParams } from '@angular/http';
addUser(info){
    console.log(info);
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers, withCredentials: true });
    console.log(options);
    return this._http.post("http://localhost/simple_api/insert.php",info, options)
      .pipe(map(()=>""));
  }

insert.php

<?php
$data = json_decode(file_get_contents("php://input"));
header("Access-Control-Allow-Origin: http://localhost:4200");
header("Access-Control-Allow-Headers: X-CSRF-Token, Origin, X-Requested-With, Content-Type, Accept");
?>

Consoling the values of the header, Xsrf-Token was not set. How am I supposed to set the Xsrf-Token values?


UPDATE:

import {HttpClient, HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";

constructor(private _http:HttpClient) { }

  addUser(info){
    console.log(info);
    // let headers = new Headers({ 'Content-Type': 'application/json' });
    // let options = new RequestOptions({ headers: headers, withCredentials: true });
    // console.log(options);
    return this._http.post("http://localhost/simple_api/insert.php",info)
        .subscribe(
                data => {
                    console.log("POST Request is successful ", data);
                },
                error => {
                    console.log("Error", error);
                }
            ); 
  }

app.module.ts

import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";

imports: [
    ...
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-CSRF-TOKEN'
    })
  ],
...

回答1:


Add the following header to your php code

header("Access-Control-Allow-Credentials: true");

Also, why are you mixing old HttpModule and new HttpClient module? RequestOptions and Headers are deprecated in angular 6

If you use HttpClient, content type is already set to json by default, and withCredentials is set by the HttpClientXsrfModule.

Your request can just be simplified to

 return this._http.post("http://localhost/simple_api/insert.php",info);

Edit The default interceptor created behind the scene by HttpClientXsrfModule does not seem to handle absolute urls....

https://github.com/angular/angular/issues/18859




回答2:


Server-side, XSRF-TOKEN is not a header, but a cookie to set beforehand. This cookie should be sent from the server to the page in which your Angular app lives, that is, in the example below, the template 'some.template.html.twig' should load the Angular app.

This way Angular will add and send the correct X-XSRF-etc. header properly.

Please note: the cookie must be generated with the HttpOnly option set to FALSE, otherwise Angular won't see it.

E.g. if you're using Symfony, in a controller action you could set a XSRF cookie as follows:

namespace App\Controller;

use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class MyController extends Controller
{
  /**
   * Disclaimer: all contents in Route(...) are example contents
   * @Route("some/route", name="my_route")
   * @param Request $request
   * @return \Symfony\Component\HttpFoundation\Response
   */
  public function someAction(Request $request, CsrfTokenManagerInterface $csrf)
  {
    $response = $this->render('some.template.html.twig');
    if(!$request->cookies->get('XSRF-TOKEN')){
      $xsrfCookie = new Cookie('XSRF-TOKEN',
        'A_Token_ID_of_your_Choice',
        time() + 3600, // expiration time 
        '/', // validity path of the cookie, relative to your server 
        null, // domain
        false, // secure: change it to true if you're on HTTPS
        false // httpOnly: Angular needs this to be false
      ); 
      $response->headers->setCookie($xsrfCookie);
    }

    return $response;
  }
}


来源:https://stackoverflow.com/questions/52342195/issue-in-adding-xsrf-token-in-an-angular-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!