【问题标题】:Angular 2: add csrf parameter to noNgFormAngular 2:将 csrf 参数添加到 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的值?

【问题讨论】:

    标签: angular spring-security csrf csrf-protection


    【解决方案1】:

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

    1. angular2-cookie 插件
    2. CSRFService
    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 的表单中添加 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>
    

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

    【讨论】:

      猜你喜欢
      • 2016-12-25
      • 1970-01-01
      • 2016-07-05
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      • 2014-09-19
      相关资源
      最近更新 更多