前言
我在重写odoo的登录界面的时候,弃用了odoo原来的界面,而是自己重新写了一个html页面出来,但在设置了<form method="POST">后提交表单时发现,odoo返回了一个 invalid csrf token的错误,于是开始自己着手找原因.
<form class="oe_login_form" role="form" method="post" onsubmit="this.action = this.action + location.hash" action="/web/login">
<!-- 请注意,下面这个input是关键 -->
<input type="hidden" name="csrf_token" value="5465456131654645">
<div class="form-group field-login">
<label for="login" class="control-label">Email</label>
<input type="text" name="login" id="login" class="form-control" required="required" autofocus="autofocus" autocapitalize="off">
</div>
<div class="form-group field-password">
<label for="password" class="control-label">密码</label>
<input type="password" name="password" id="password" class="form-control" required="required">
</div>
<input type="hidden" name="redirect"/>
<div class="clearfix oe_login_buttons">
<button type="submit" class="btn btn-primary">登录</button>
</div>
</form>
可以发现,odoo在登录时,除了会提交用户名(login)和密码(password)之外,还会隐晦地提交一个csrf_token,通过度娘搜索后得知,这是为了防止跨站请求伪造(CSRF)的.
跨站请求伪造(CSRF)
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。 --------以上转自度娘
如何应对CSRF
这篇文章就写得非常好,如何检测漏洞,如何应对都有写:
http://blog.csdn.net/stpeace/article/details/53512283
这里就文章中的3种应对方法做下总结:
1.验证http请求中request headers中的referer字段:
通常请求头中的referer字段是指向发起请求的网站的,验证时发现referer指向的不是自己的网站站点,则可以拒绝这个请求.
弊端是由于涉及用户隐私问题,用户可以设置浏览器,使其发送的请求中不含referer字段;同时,在某些非常旧的浏览器(如ie6,呵呵),仍然有方法修改请求中的referer字段.
2.在请求的参数中添加token验证:
用户在登录时,设置一个有限期的token并放入session中,网站每次处理请求时都验证一次这个token.
弊端是大量的form表单都需要添加一个<input/>来提交token,同时如果是GET请求的话,token会添加在url的末端,这样同样会有泄露token的风险.
3.使用XMLHttpRequest自定义header,往header中添加token字段:
这个方法具体就是用XMLHttpRequest来发送所有请求,弊端是XMLHttpRequest这个类的使用局限性太大,几乎重写整个网站
总结
由于odoo自身模块中需要提交表单的地方比较少,目前我遇到的就只有登录时需要提交,同时odoo可能考虑到使用ie6等老爷车浏览器的可能性比较小,所以采取了第二种解决方案,不过由于csrf_token是存于session中的,所以以后服务器集群需要共享session的时候可能会遇到问题,不过到时再看就是了.
网友评论