Dans la documentation angulaire, il est mentionné que la variable angulaire httpclient
enverra automatiquement la valeur du cookie XSRF-TOKEN
dans l'en-tête X-XSRF-TOKEN
de la demande de publication. Lien vers la documentation
Mais il n'envoie pas l'en-tête pour moi. Voici mon code
Nodejs code pour définir le cookie
router.get('/set-csrf',function(req,res,next){
res.setHeader('Set-Cookie', "XSRF-TOKEN=abc;Path=/; HttpOnly; SameSite=Strict");
res.send();
})
J'ai utilisé le httpclient dans app.module.ts
imports: [
HttpClientModule
]
** Le code ci-dessus est juste pour le débogage. Je n'ai pas de point de terminaison set-csrf.
Mais il n'envoie pas d'en-tête lorsque j'envoie une demande de publication. Je ne suis pas capable de déboguer.
J'ai ajouté le problème dans le répertoire github d'angular. HttpXsrfInterceptor vérifie si la requête est GET ou HEAD, ou si elle commence par http. Si true, l'ajout de l'en-tête est ignoré.
Voici le code dans Classe HttpXsrfInterceptor
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const lcUrl = req.url.toLowerCase();
// Skip both non-mutating requests and absolute URLs.
// Non-mutating requests don't require a token, and absolute URLs require special handling
// anyway as the cookie set
// on our Origin is not the same as the token expected by another Origin.
if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') ||
lcUrl.startsWith('https://')) {
return next.handle(req);
}
const token = this.tokenService.getToken();
// Be careful not to overwrite an existing header of the same name.
if (token !== null && !req.headers.has(this.headerName)) {
req = req.clone({headers: req.headers.set(this.headerName, token)});
}
return next.handle(req);
}
Je ne sais pas pourquoi ils ont sauté pour la partie http/s. Voici mon numéro dans github
Ce que vous recherchez est HttpClientXsrfModule
.
Veuillez en lire plus à ce sujet ici: https://angular.io/api/common/http/HttpClientXsrfModule .
Votre utilisation devrait être comme ceci:
imports: [
HttpClientModule,
HttpClientXsrfModule.withConfig({
cookieName: 'My-Xsrf-Cookie', // this is optional
headerName: 'My-Xsrf-Header' // this is optional
})
]
De plus, si votre code cible l'API via une URL absolue, l'intercepteur CSRF par défaut ne fonctionnera pas immédiatement. Au lieu de cela, vous devez implémenter votre propre intercepteur, qui n'ignore pas les routes absolues.
@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headerName = 'X-XSRF-TOKEN';
let token = this.tokenExtractor.getToken() as string;
if (token !== null && !req.headers.has(headerName)) {
req = req.clone({ headers: req.headers.set(headerName, token) });
}
return next.handle(req);
}
}
Et enfin, ajoutez-le à vos fournisseurs:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }
]
Je suppose que la bonne méthode est withOptions
. J'ai utilisé withConfig et j'ai eu l'erreur Property 'withConfig' does not exist on type 'typeof HttpClientXsrfModule'.
Il s'agit d'un problème de frappe dans la documentation. Vous devez utiliser "withOptions" à la place de HttpClientXsrfModule.withOptions({
cookieName: 'My-Xsrf-Cookie',
headerName: 'My-Xsrf-Header',
})
En utilisant la version angulaire récente, j'ai rencontré le problème suivant. Alors que le jeton est transmis au client en utilisant le nom d’en-tête 'XSRF-TOKEN', la réponse doit renvoyer le jeton sous le nom d’en-tête 'X-XSRF-TOKEN'. Voici donc une version légèrement modifiée du code de Miroslav ci-dessus qui fonctionne pour moi.
@Injectable()
export class HttpXSRFInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
}
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);
}
}