Angular 2:将csrf参数添加到noNgForm

Angular 2: add csrf parameter to noNgForm

今天在 angular SPA 上从 html 模板提交表单时遇到了问题。 首先,带有提交的简单表单无法开箱即用,因为 angular 捕获了不允许提交表单的提交事件。

   <form action="/api/connect/facebook" method="POST">
       <input type="hidden" name="scope" value="email" />
       <button type="submit" class="btn btn-primary btn-block"><i class="icon-facebook"></i> &nbsp;&nbsp;&nbsp;Login via Facebook</button>
   </form>

要让 angular 忽略它并让您的浏览器执行 post 您必须添加 ngNoForm header:

   <form ngNoForm action="/api/connect/facebook" method="POST">
       <input type="hidden" name="scope" value="email" />
       <button type="submit" class="btn btn-primary btn-block"><i class="icon-facebook"></i> &nbsp;&nbsp;&nbsp;Login via Facebook</button>
   </form>

这对于 SPA 来说可能不是很常见,因为这样的表单提交将使浏览器远离 SPA,但这正是我所需要的。

好东西 - 我使用 spring-boot 作为我的后端,所以使用 spring-security 它有很好的 csrf 和 cors 保护,不允许我提交表单。我收到异常:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'

所以,问题是如何为angular模板提供csrf的值?

我找到了一个很好的示例,说明如何在 JHipster 框架中完成此操作。 需要三件事:

  1. angular2-cookie 插件
  2. CSRF服务
  3. 向表单添加隐藏参数

添加angular2-cookie插件很简单:

npm install angular2-cookie --save

但是,您需要将所有必需的映射添加到 SystemJS 或您使用的任何模块框架。对于 SystemJS,一切都解释得很好 here。仔细阅读,因为我第一次忘记制作:

import { CookieService } from 'angular2-cookie/services/cookies.service';

@NgModule({
  providers: [ CookieService ],
})
export class AppModule { }

现在,CSRFService:

import { Injectable } from '@angular/core';
import { CookieService } from 'angular2-cookie/core';

@Injectable()
export class CSRFService {

    constructor(private cookieService: CookieService) {}

    getCSRF(name?: string) {
        name = `${name ? name : 'XSRF-TOKEN'}`;
        return this.cookieService.get(name);
    }
}

现在,您需要将它注入呈现模板的组件:

import {Component, OnInit} from '@angular/core';
import {CSRFService} from './csrf.service';

@Component({
    moduleId: module.id,
    selector: 'login-form',
    templateUrl: 'login.component.html',
    styleUrls: ['login.component.css']
})
export class LoginComponent implements OnInit {

    private csrf: string;

    constructor(private csrfService: CSRFService) { }

    ngOnInit() {
        this.csrf = this.csrfService.getCSRF();
    }
}

最后不要忘记在 login.component.html 中的表单中添加隐藏参数:

<form ngNoForm action="/api/connect/facebook" method="POST">
    <input name="_csrf" type="hidden" value="{{ csrf }}"/>
    <input type="hidden" name="scope" value="email" />
    <button type="submit" class="btn btn-primary btn-block"><i class="icon-facebook"></i> &nbsp;&nbsp;&nbsp;Login via Facebook</button>
</form>

希望,这对任何人都有帮助,因为我花了半天时间试图弄清楚如何实现我想要的。