Angular 2:将 csrf 参数添加到 noNgForm

Posted

技术标签:

【中文标题】Angular 2:将 csrf 参数添加到 noNgForm【英文标题】:Angular 2: add csrf parameter to noNgForm 【发布时间】:2017-05-30 16:34:13 【问题描述】:

今天遇到了从 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 忽略这一点并让您的浏览器执行帖子,您必须添加 ngNoForm 标头:

   <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 保护不让我提交表单。我得到了例外:

在请求参数“_csrf”上发现无效的 CSRF 令牌“null” 或标题“X-CSRF-TOKEN”

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

【问题讨论】:

【参考方案1】:

我发现了一个很好的例子,这是如何在 JHipster 框架中完成的。 需要三样东西:

    angular2-cookie 插件 CSRFService 向表单添加隐藏参数

添加 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 的表单中添加 hidden 参数:

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

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

【讨论】:

以上是关于Angular 2:将 csrf 参数添加到 noNgForm的主要内容,如果未能解决你的问题,请参考以下文章

使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF 令牌传递给 Angular

将 csrf 令牌和参数名称添加到注销链接

Angular2 - 将 routerLink 参数添加到所选表值

Angular2 和 Django:CSRF 令牌头痛

如何在 Angular 2 中添加类到主机?

Angular 2/Spring Security CSRF 实现问题