You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Play框架如何传递CSRF Token?Angular前端未在头/Cookie中发现该Token

Hey there! Let's work through this CSRF token issue with your Play + Angular setup. I've dealt with this exact scenario before, so here's a breakdown of what's going on and how to fix it:

Understanding the Play CSRF Behavior First

First off, it's normal that you don't see a CSRF token in the request headers/cookies when fetching static files like index.html, JS, or CSS. Play doesn't automatically attach CSRF tokens to GET requests for static resources—CSRF protection is primarily designed for requests that modify server state (POST, PUT, DELETE, etc.). The key here is to make sure your Angular app can grab the CSRF token early (from the initial page load) and then attach it to all state-changing requests later.

Step-by-Step Fixes

1. Render the CSRF Token in Your Play Template

Since your Angular app is hosted by Play, you need to inject the CSRF token into the initial index.html (which should be a Play template file, not a static HTML file).

  • Rename your static index.html to index.scala.html and move it into Play's views directory.
  • Add a meta tag to the <head> section that outputs the CSRF token using Play's template helper:
    <meta name="csrf-token" content="@csrfToken.value">
    
  • Update your Play route to serve this template instead of the static file:
    GET     /       controllers.HomeController.index()
    
  • In your HomeController, return the template (make sure to pass the implicit request so the CSRF token is available):
    def index() = Action { implicit request =>
      Ok(views.html.index())
    }
    

2. Configure Angular to Use the Token

Now that the token is in the page's meta tags, create an Angular HTTP interceptor to automatically attach it to all state-changing requests:

  • Create a csrf.interceptor.ts file:
    import { Injectable } from '@angular/core';
    import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
    import { Observable } from 'rxjs';
    
    @Injectable()
    export class CsrfInterceptor implements HttpInterceptor {
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // Grab the token from the meta tag
        const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
        
        // Only add the token to non-GET/HEAD/OPTIONS requests (the ones that need CSRF protection)
        if (csrfToken && !req.method.match(/GET|HEAD|OPTIONS/)) {
          const modifiedRequest = req.clone({
            headers: req.headers.set('X-CSRF-Token', csrfToken)
          });
          return next.handle(modifiedRequest);
        }
        
        return next.handle(req);
      }
    }
    
  • Register the interceptor in your AppModule:
    import { HTTP_INTERCEPTORS } from '@angular/common/http';
    import { CsrfInterceptor } from './csrf.interceptor';
    
    @NgModule({
      providers: [
        { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true }
      ]
    })
    export class AppModule { }
    

3. Verify Play's CSRF Configuration

Double-check your application.conf to ensure Play is set up to recognize the token header:

play.filters.csrf {
  token.name = "X-CSRF-Token"  # Matches the header we're sending from Angular
  cookie.name = "PLAY_CSRF_TOKEN"
  # For development, you can disable secure cookies if you're not using HTTPS
  cookie.secure = false
}
Quick Notes to Keep in Mind
  • You don't need to worry about CSRF tokens on static asset requests (GET for JS/CSS/HTML)—those are safe from CSRF attacks by design.
  • If you were expecting the token to be in a cookie, Play will set the PLAY_CSRF_TOKEN cookie automatically when you render the template with the @csrfToken() helper, but using the meta tag + interceptor is the cleaner approach for Angular apps.

Give these steps a shot, and let me know if you hit any roadblocks!

内容的提问来源于stack exchange,提问作者Manu Chadha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:55:03