【发布时间】:2018-03-09 10:40:43
【问题描述】:
我遇到了奇怪的问题。我正在我的网站上实现购物车功能,并使用会话来存储购物车位置。我有一个 POST 操作来向购物车添加新位置,并且我启用了 CSRF 过滤器来保护网站。我在产品页面上用 ajax 调用它,所以第一次调用没问题,但第二次调用未授权,日志中有 [CSRF] Check failed because no token found in headers for /cart。但它有。我称之为:
$("form").submit(function(e){
e.preventDefault();
$.ajax({
url: '/cart',
method: 'POST',
data: getCartPosition(),
beforeSend: function(xhr){xhr.setRequestHeader('Csrf-Token', $('input[name=csrfToken]').val());},
success: function (data, textStatus) {
alert('Added!');
},
error: function (error) {
alert('Error!');
}
});
});
我将 CSRF 令牌放在模板中的某处:
@CSRF.formField
它正在请求中:
我已经在配置中启用了这个
play.filters.csrf.bypassCorsTrustedOrigins=true
play.filters.hosts {
# Allow requests to example.com, its subdomains, and localhost:9000
allowed = ["localhost:9000", "localhost:4200"]
}
但奇怪的是它似乎将 csrfToken 置于会话中,因为在请求失败后我有这样的会话
Session(Map(cart -> {"positions":
[{"trackId":1},{"trackId":24},{"trackId":20}]},
username -> user,
token -> 0639d0b0-e7c8-4e82-9aad-2a43044e72db,
csrfToken -> e705413843ea96a6491a0e9e800ba36a712c4f70-1506542471068-0baeef7535eb9c889fb6fed2))
不知道为什么会出现,我的 add2cart 操作如下所示:
private def cartAction(addToCartForm: Form[CartPosition], action: (Cart, CartPosition) => Cart)(implicit request: UserRequest[Any]) = {
addToCartForm.fold(
_ => BadRequest("Error!"),
position => {
getCart match {
case Some(cart) => Ok("Ok").withSession("cart" -> Json.toJson(action(cart, position)).toString(), "username" -> request.session.get("username").getOrElse(""), "token" -> request.session.get("token").getOrElse(""))
case _ => Ok("Ok, no").withSession("cart" -> Json.toJson(action(Cart(Seq.empty), position)).toString())
}
}
)
}
def addToCart() = guestAction { implicit request =>
cartAction(addToCartForm.bindFromRequest, addCartPos)
}
而 addCartPos 只是将位置添加到 json
【问题讨论】:
-
切换到 GET 并且它可以工作,但仍然没有弄清楚为什么它不能与 POST 一起工作
-
实际上我在会话中得到 csrfToken 不仅是购物车,它只是把它放在任何地方
-
我遇到了类似的问题,我使用
addingToSession而不是withSession解决了这个问题。我猜后者会覆盖会话并清除渲染模板时放入其中的 csrf 令牌。不确定这是否与您遇到的问题相同,因为我不太了解 Play 中的 csrf 机制是如何工作的。
标签: scala playframework csrf