我有一个使用phonegap 2.3.0 for Windows Phone 8 SDK通过iframe加载的webapp。通过iframe加载它的问题是,当我发送Can't verify CSRF token authencity
请求时,它会在Rails端导致$.post()
。
我尝试了几种方法,例如使用令牌覆盖$.post()
以$.ajax()
setHeaderRequest
$.ajaxSetup()
以及protect_from_forgery
当我停用verify_authenticity_token
或 $.post(url, {app: {played: tiles}, no: no}, function (response) {
linkTo('#app_button', response['next']);
});
时,应用会正确加载。
我认为问题的原因是因为webapp位于另一个域(跨域问题),而csrf只是试图阻止点击劫持。有办法绕过这个问题吗?
以下是我发布的示例:
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').prop('content'));
}
});
示例:
[2539 - 2013/03/06 15:37:42] (INFO) Parameters: {"app"=>{"played"=>"tiles"}, "no"=>"no", "authenticity_token"=>"yBpUImzjtKGIejh/WCekv/GCi1zjPirib22plqfLJ1Y="}
[2539 - 2013/03/06 15:37:42] (WARN) WARNING: Can't verify CSRF token authenticity
[2539 - 2013/03/06 15:37:42] (INFO) User agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)
[2539 - 2013/03/06 15:37:42] (DEBUG) User Load (1.8ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
[2539 - 2013/03/06 15:37:42] (DEBUG) CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
[2539 - 2013/03/06 15:37:42] (DEBUG) CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
[2539 - 2013/03/06 15:37:42] (WARN) Lost session [118.143.97.82] (/locations/1/games) - Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)
[2539 - 2013/03/06 15:37:42] (DEBUG) CACHE (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` IS NULL LIMIT 1
编辑: 我已经能够将真实性令牌作为参数传递到我的发布请求中,但具有相同的错误。我开始相信错误不是由令牌引起的。错误发生的其他原因是什么?
记录:
{{1}}
答案 0 :(得分:2)
答案是因为没有阻止会话存储的P3P标头。您需要添加一个P3P标头来解决此问题。
答案 1 :(得分:1)
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" >
将此隐藏字段添加到表单中。我修复了与“无法验证CSRF令牌真实性”
相同的问题答案 2 :(得分:1)
您可以针对某些控制器操作关闭CSRF。您可以为AJAX调用创建一个新操作(假设iframe)并添加到控制器中:
skip_before_filter :verify_authenticity_token, :only => [:iframe]
答案 3 :(得分:1)
问题是您需要在Ajax POST请求之后获取新令牌,因为一旦使用了令牌,它就会失效。以下是执行此操作的代码:
每当发送POST回复时,在rails中将这些参数添加到响应中:
def someMethod:
result[:csrfParam] = request_forgery_protection_token
result[:csrfToken] = form_authenticity_token
render :json => result
end
现在在JS方面,在每个POST方法的成功函数中,您可以调用此函数:
var setCsrfToken = function(param, token) {
if(param == null || token == null) {
console.error("New CSRF param/token not present");
}
$("input[name='" + param + "']").val(token);
}
像这样:
setCsrfToken(result["csrfParam"], result["csrfToken"]);
此函数将重置所有POST表单中的所有authenticity_token参数,以便下一个请求具有有效的标记。您需要确保在每次POST调用中都会发生这种情况,否则您将继续面临此问题。
此外,CSRF不是为了防止点击劫持,而是一个单独的攻击,其他网站可以让用户点击一个链接,用你的会话在你的网站上执行一个动作。
答案 4 :(得分:0)
@ user1555300的回答是正确的,只是提供了详细信息。
在useService = new Intent(CountDownAct.this, CountDownService.class);
useService.putExtra("the", actualTimeFiniliazedInMilliSeconds);
startService(useService);
中添加此内容
application_controller.rb
还添加此方法
before_filter :set_p3p
确保它位于private
# for IE, Facebook, and iframe sessions
def set_p3p
headers['P3P'] = 'CP="ALL DSP COR CURa ADMa DEVa OUR IND COM NAV"'
end
而不是常规控制器上。