4

我有一个使用 phonegap 2.3.0 for Windows Phone 8 SDK 通过 iframe 加载的 webapp。通过 iframe 加载它的问题是,Can't verify CSRF token authencity当我发送$.post()请求时,它会在 Rails 端引起。

我尝试了几种方法,例如用令牌覆盖$.post()要使用的$.ajax()to setHeaderRequest,以及$.ajaxSetup()

当我禁用protect_from_forgeryorverify_authenticity_token时,应用程序正确加载。

我相信这个问题是因为 webapp 位于另一个域中(跨域问题),而 csrf 只是试图防止点击劫持。有没有办法绕过这个问题?

这是我如何发布的示例:

    $.post(url, {app: {played: tiles}, no: no}, function (response) {
      linkTo('#app_button', response['next']);
    });

例子:

    $.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
4

5 回答 5

3

答案是因为没有阻止会话存储的 P3P 标头。您需要添加 P3P 标头来解决此问题。

于 2013-03-20T04:12:54.910 回答
1
   <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" >

将此隐藏字段添加到您的表单中。我已经修复了与“无法验证 CSRF 令牌真实性”相同的问题

于 2013-03-06T05:49:01.297 回答
1

您可以为某些控制器操作关闭 CSRF。您可以为 AJAX 调用创建一个新操作(比如 iframe)并添加到控制器中:

skip_before_filter :verify_authenticity_token,  :only => [:iframe]
于 2013-03-06T05:51:54.647 回答
1

问题是您需要在 Ajax POST 请求之后获取新令牌,因为一旦使用令牌,它就会失效。这是执行此操作的代码:

在 Rails 中,每当发送 POST 回复时,将这些参数添加到响应中:

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 不是为了防止点击劫持,它完全是一种单独的攻击,另一个网站可以让用户点击一个链接,该链接通过用户的会话在您的网站上执行操作。

于 2013-04-08T01:08:18.873 回答
0

@user1555300 的答案是正确的,只是提供了详细信息。

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

确保这是在application_controller.rb非常规控制器上。

于 2015-07-25T01:55:18.363 回答