W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
跨站請求偽造(Cross-site request forgery), 簡稱為 XSRF,是 Web 應(yīng)用中常見的一個(gè)安全問題。前面的鏈接也詳細(xì)講述了 XSRF 攻擊的實(shí)現(xiàn)方式。
當(dāng)前防范 XSRF 的一種通用的方法,是對每一個(gè)用戶都記錄一個(gè)無法預(yù)知的 cookie 數(shù)據(jù),然后要求所有提交的請求(POST/PUT/DELETE)中都必須帶有這個(gè) cookie 數(shù)據(jù)。如果此數(shù)據(jù)不匹配 ,那么這個(gè)請求就可能是被偽造的。
beego 有內(nèi)建的 XSRF 的防范機(jī)制,要使用此機(jī)制,你需要在應(yīng)用配置文件中加上 enablexsrf 設(shè)定:
enablexsrf = true
xsrfkey = 61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o
xsrfexpire = 3600
或者直接在 main 入口處這樣設(shè)置:
beego.EnableXSRF = true
beego.XSRFKEY = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o"
beego.XSRFExpire = 3600 //過期時(shí)間,默認(rèn)1小時(shí)
如果開啟了 XSRF,那么 beego 的 Web 應(yīng)用將對所有用戶設(shè)置一個(gè) _xsrf 的 cookie 值(默認(rèn)過期 1 小時(shí)),如果 POST PUT DELET 請求中沒有這個(gè) cookie 值,那么這個(gè)請求會(huì)被直接拒絕。如果你開啟了這個(gè)機(jī)制,那么在所有被提交的表單中,你都需要加上一個(gè)域來提供這個(gè)值。你可以通過在模板中使用 專門的函數(shù) XSRFFormHTML() 來做到這一點(diǎn):
過期時(shí)間上面我們設(shè)置了全局的過期時(shí)間 beego.XSRFExpire,但是有些時(shí)候我們也可以在控制器中修改這個(gè)過期時(shí)間,專門針對某一類處理邏輯:
func (this *HomeController) Get(){
this.XSRFExpire = 7200
this.Data["xsrfdata"]=template.HTML(this.XSRFFormHTML())
}
在 Controller 中這樣設(shè)置數(shù)據(jù):
func (this *HomeController) Get(){
this.Data["xsrfdata"]=template.HTML(this.XSRFFormHTML())
}
然后在模板中這樣設(shè)置:
<form action="/new_message" method="post">
{{ .xsrfdata }}
<input type="text" name="message"/>
<input type="submit" value="Post"/>
</form>
如果你提交的是 AJAX 的 POST 請求,你還是需要在每一個(gè)請求中通過腳本添加上 _xsrf 這個(gè)值。下面是在 AJAX 的 POST 請求,使用了 jQuery 函數(shù)來為所有請求都添加 _xsrf 值:
jQuery cookie插件:https://github.com/carhartl/jquery-cookie base64 插件:http://phpjs.org/functions/base64_decode/
jQuery.postJSON = function(url, args, callback) {
var xsrf, xsrflist;
xsrf = $.cookie("_xsrf");
xsrflist = xsrf.split("|");
args._xsrf = base64_decode(xsrflist[0]);
$.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
success: function(response) {
callback(eval("(" + response + ")"));
}});
};
通過擴(kuò)展 ajax 給每個(gè)請求加入 xsrf 的 header
需要你在 html 里保存一個(gè) _xsrf 值
func (this *HomeController) Get(){
this.Data["xsrf_token"] = this.XSRFToken()
}
放在你的 head 中
<head>
<meta name="_xsrf" content="{{.xsrf_token}}" />
</head>
擴(kuò)展 ajax 方法,將 _xsrf 值加入 header,擴(kuò)展后支持 jquery post/get 等內(nèi)部使用了 ajax 的方法
var ajax = $.ajax;
$.extend({
ajax: function(url, options) {
if (typeof url === 'object') {
options = url;
url = undefined;
}
options = options || {};
url = options.url;
var xsrftoken = $('meta[name=_xsrf]').attr('content');
var headers = options.headers || {};
var domain = document.domain.replace(/\./ig, '\\.');
if (!/^(http:|https:).*/.test(url) || eval('/^(http:|https:)\\/\\/(.+\\.)*' + domain + '.*/').test(url)) {
headers = $.extend(headers, {'X-Xsrftoken':xsrftoken});
}
options.headers = headers;
return ajax(url, options);
}
});
對于 PUT 和 DELETE 請求(以及不使用將 form 內(nèi)容作為參數(shù)的 POST 請求)來說,你也可以在 HTTP 頭中以 X-XSRFToken 這個(gè)參數(shù)傳遞 XSRF token。
如果你需要針對每一個(gè)請求處理器定制 XSRF 行為,你可以重寫 Controller 的 CheckXSRFCookie 方法。例如你需要使用一個(gè)不支持 cookie 的 API, 你可以通過將 CheckXSRFCookie() 函數(shù)設(shè)空來禁用 XSRF 保護(hù)機(jī)制。然而如果 你需要同時(shí)支持 cookie 和非 cookie 認(rèn)證方式,那么只要當(dāng)前請求是通過 cookie 進(jìn)行認(rèn)證的,你就應(yīng)該對其使用 XSRF 保護(hù)機(jī)制,這一點(diǎn)至關(guān)重要。
XSRF 之前是全局設(shè)置的一個(gè)參數(shù),如果設(shè)置了那么所有的 API 請求都會(huì)進(jìn)行驗(yàn)證,但是有些時(shí)候API 邏輯是不需要進(jìn)行驗(yàn)證的,因此現(xiàn)在支持在controller 級(jí)別設(shè)置屏蔽:
type AdminController struct{
beego.Controller
}
func (a *AdminController) Prepare() {
a.EnableXSRF = false
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: