Node JS / Angular 2应用程序,ForbiddenError:无效的csrf标记

时间:2017-01-06 16:51:59

标签: node.js angular csrf-protection

我正在使用Node.js作为服务器端,Angular 2作为前端使用示例应用程序。

为防止CSRF攻击,我使用了" csurf"中间件 以下是设置中间件的相关代码

// cookie parser
app.use(cookieParser());

// express session middleware , this should be after cookie parser
app.use(session({secret:'clickclick'}));

app.use(session({ 
secret: 'clickclick',
cookie: {
    path:'/',
    httpOnly:true,
    maxAge:null
}
}));

// CSRF middleware
app.use(csurf());

在node.js下面设置路由集" _csrf"头

router.get('/:id/products/:pid' ,  wrap(function *(req , res , next) {

try 
{
    console.log('url' , req.url);
    res.setHeader('_csrf', req.csrfToken());
    let product = yield category.getProduct(req , res , next);
    res.send(product);
}
catch(err) 
{
    res.status(500).send(err);
}

})) 

上述路线' /:id / products /:pid'从我的Angular 2服务方法下面调用

// Get Product
GetProduct(id:string, pid:string):Observable<Product> {

    return this.http.get('./categories/' + id + '/products/' + pid)
                    .map(data =>{ let headers:Headers = data.headers; 
                                  this.csrfToken = headers.get('_csrf') ; 
                               return data.json() })
                    .catch(this.handleError);
}

此方法将从服务器返回的_csrf标头分配给&#34; this.csrfToken&#34;属性。

当以下服务方法发出AJAX POST请求时,它使用&#34; this.csrfToken&#34;通过上述方法设置的属性值并设置标题&#34; _csrf&#34;值。

// Add an item to cart
 AddTocart(product:Product) 
 {
    let item = { pid:product._id , name:product.name , price:product.price , qty:1 , total:product.price  };   
    //this.cart.push(item);

    // make an AJAX call to save the item in server session
    let url = './cart/add';
    let headers = new Headers({'Content-Type':'application/json' , '_csrf':this.csrfToken});
    let requestOptions = new RequestOptions({headers:headers});

    this.http.post(url , item , requestOptions)
             .map(data => {                                
                            this.cart.push(item);
                          }
             )
             .catch(this.handleError)
             .subscribe( data => { });                

}

以下是GetProduct服务方法的响应标头。 enter image description here

以下是&#34; AddTocart&#34;的请求标题。服务方法。

enter image description here

知道是什么导致&#34; ForbiddenError:无效的csrf令牌&#34;错误。 如果我需要提供更多信息或者提供的信息不清楚,请告诉我。

1 个答案:

答案 0 :(得分:0)

我知道这是一个较旧的问题,但我在此处添加此问题,以防将来有人偶然发现它。处理类似的项目并遇到相同的错误,我通过在POST请求中添加XSRF-TOKEN标头来修复它,其值取自$.cookie("XSRF-TOKEN")(使用jquery和cookies插件)。根据文档,_csrf也应该有用。

来自the project page

The default value is a function that reads the token from the following locations, in order:

req.body._csrf - typically generated by the body-parser module.
req.query._csrf - a built-in from Express.js to read from the URL query string.
req.headers['csrf-token'] - the CSRF-Token HTTP request header.
req.headers['xsrf-token'] - the XSRF-Token HTTP request header.
req.headers['x-csrf-token'] - the X-CSRF-Token HTTP request header.
req.headers['x-xsrf-token'] - the X-XSRF-Token HTTP request header.

据我所知,错误似乎来自POST / PUT请求,包括正确的cookie,但是nodejs / csurf并没有在那里寻找它们。

在您的特定情况下,_csrf应与请求主体一起位于请求正文中,或者标题应重命名为csrf-token,或其他选项之一。