javascript – 如何保护Angular 2中的http帖子到Express Server

如何保护从angular2应用程序到Express服务器的邮件调用

在我的angular2应用程序中,我有一个以下HTTP Post.

const headers = new Headers();
    headers.append('Content-Type','application/json');

    const data = {
      email: this.form.value.email
    };

    this.http.post('http://localhost:8080/api/user/email',data,{
      headers: headers
    })

现在我想确保只有我的angular 2应用程序可以对用户api进行post调用.我结合Express和Angular 2对csrf进行了一些研究.在我的Angular 2应用程序中,我对app.module.ts文件进行了以下实现.

import { HttpModule,XSRFStrategy,CookieXSRFStrategy } from '@angular/http';

providers: [  {
            provide: XSRFStrategy,useValue: new CookieXSRFStrategy('csrftoken','X-CSrftoken')
        } ]

我认为这是向Angular 2实现XSRFStrategy的正确方法吗?

对于Express中的实现我遵循了一些教程,但没有任何成功.我收到的大部分时间:

ForbiddenError: invalid csrf token

如何在Express api中实现CSRF部分.这是我的Express配置:

// call the packages we need
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var csrf = require('csurf');

app.use(bodyParser.urlencoded({
  extended: false
}));
app.use(bodyParser.json());

var port = process.env.PORT || 8080; // set our port

// ROUTES FOR OUR API
// =============================================================================
var router = express.Router();
router.use(function (req,res,next) {
  console.log('Something is happening.');
  res.setHeader("Access-Control-Allow-Origin","http://localhost:4200");
  res.setHeader("Access-Control-Allow-Credentials","true");
  res.setHeader("Access-Control-Allow-Methods","POST");
  res.setHeader("Access-Control-Allow-Headers","Access-Control-Allow-Headers,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers");
  res.setHeader('Content-Type','application/json');
  next();
});

app.use('/api',router);

router.post('/user/email',function (req,res) {
 ..... [how to make sure that this post can only be fired from my angular 2 application ]
}

更新#1

做了一些研究并在Angular 2文档中找到了以下内容

//By default,Angular will look for a cookie called `'XSRF-TOKEN'`,and set
//* an HTTP request header called `'X-XSRF-TOKEN'` with the value of the cookie on each request,

所以在我的Express应用程序中添加了以下部分:

const cookieOptions = {
  key: 'XSRF-TOKEN',secure: false,httpOnly: false,maxAge: 3600000
}

var csrfProtection = csrf({
  cookie: cookieOptions
})

在后期路线我实施了如下保护:

router.post('/user/email',csrfProtection,res) {
      console.log('post incomming');
}):

我收到了以下响应标头

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Access-Control-Allow-Headers,Access-Control-Request-Headers
Access-Control-Allow-Methods:POST
Access-Control-Allow-Origin:http://localhost:4200
Connection:keep-alive
Content-Length:1167
Content-Type:text/html; charset=utf-8
Date:Mon,21 Nov 2016 20:07:12 GMT
set-cookie:XSRF-TOKEN=O4JKkjAZRik2H7ml0DoxDc8s; Max-Age=3600000; Path=/
X-Content-Type-Options:nosniff
X-Powered-By:Express

并且请求标头:

Accept:*/*
Accept-Encoding:gzip,deflate,br
Accept-Language:en-US,en;q=0.8,nl;q=0.6
Connection:keep-alive
Content-Length:38
content-type:application/json
Host:localhost:8080
Origin:http://localhost:4200
Referer:http://localhost:4200/profile/users

解决方法

如何使用Angular2和Express实现CSRF保护

认情况下,Angular将查找名为“XSRF-TOKEN”的cookie并进行设置
一个名为“X-XSRF-TOKEN”的HTTP请求标头,其中包含每个请求的cookie值.

为了确保我们的后端可以设置XSRF-TOKEN cookie,我们必须代理我们对端口8080上运行的api的调用.我们可以使用proxy.config.json文件来实现.

{ 
  "/api/*" : {
    "target": "http://localhost:8080","secure": false,"logLevel": "debug" 
  }
}

在我们的package.json文件中,我们修改脚本/启动函数以使用我们的proxy.config.json文件

"scripts": {
    "start": "ng serve --proxy-config proxy.config.json",}

现在每次运行npm时,我们对/ api的调用都代理到localhost:8080.现在我们准备对我们的api服务器进行调用.

在我们的组件中,我们进行http post调用,并设置标头以使用content-type application / json.

ourfunction() {
  const headers = new Headers();
  headers.append('Content-Type','application/json');
  data = { key:value }

  this.http.post('/api/user/email',{
      headers: headers
  }).subscribe( (resp: any) => console.log('resp',resp));

}

这就是我们在Angular2方面需要做的一切.现在我们实施Express方面.

var express = require('express'); 
var app = express();
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var csrf = require('csurf');
var cors = require('cors')

我们初始化我们的应用程序并定义一些中间件以在我们的应用程序中使用

const cookieOptions = {
  key: 'XSRF-TOKEN',maxAge: 3600
}

const corsOptions = {
  origin: 'http://localhost:4200',optionsSuccessstatus: 200 // some legacy browsers (IE11,varIoUs SmartTVs) choke on 204 
};

这里我们设置用于csrf和cors中间件的选项.

const port = process.env.PORT || 8080; // set our port
const csrfProtection = csrf({ cookie: cookieOptions })
const router = express.Router();

实现middelware.订单对于获得正确的结果非常重要.

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/api',router);
app.use(cors(corsOptions));
app.use(cookieParser());
app.use(csrfProtection);

router.use(function (req,next) {
  res.setHeader('Content-Type','application/json');
  next();
});

这就是我们需要在Express方面做的所有事情.现在我们可以使用CSRF令牌保护我们的帖子调用.

Compleet express服务器文件

var express = require('express'); 
var app = express();
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var csrf = require('csurf');
var cors = require('cors')

const cookieOptions = {
  key: 'XSRF-TOKEN',varIoUs SmartTVs) choke on 204 
};

const port = process.env.PORT || 8080; // set our port
const csrfProtection = csrf({ cookie: cookieOptions })
const router = express.Router();


app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/api','application/json');
  next();
});

router.post('/user/email',res) {
  console.log('post incomming');
  console.log('req',req.body);
  res.send('testing..');
});

app.listen(port);
console.log('Magic happens on port ' + port);

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...