如何保护从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, function (req, res) {
console.log('post incomming');
}):
我收到了以下响应标头
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, 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', data, {
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',
secure: false,
httpOnly: false,
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, res, 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',
secure: false,
httpOnly: false,
maxAge: 3600
}
const corsOptions = {
origin: 'http://localhost:4200',
optionsSuccessstatus: 200 // some legacy browsers (IE11, 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', router);
app.use(cors(corsOptions));
app.use(cookieParser());
app.use(csrfProtection);
router.use(function (req, res, next) {
res.setHeader('Content-Type', 'application/json');
next();
});
router.post('/user/email', function (req, res) {
console.log('post incomming');
console.log('req', req.body);
res.send('testing..');
});
app.listen(port);
console.log('Magic happens on port ' + port);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。