问题
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