Rails中的POST 422(不可处理的实体)?由于路线或控制器?

pir*_*one 25 javascript ruby ajax ruby-on-rails httprequest

我正试图在我的网站上为用户提供"积分"或"积分"来发布有关品牌名称的推文.

我在适当的视图上有花哨的推特小部件......

<p><a  href="https://twitter.com/share" class="twitter-share-button" data-text="Check Out This Awesome Website Yay" data-via="BrandName" data-hashtags="ProductName">Tweet</a>
<div id="credited"></div>
<script>window.twttr = (function (d, s, id) {
  var t, js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src= "https://platform.twitter.com/widgets.js";
  fjs.parentNode.insertBefore(js, fjs);
  return window.twttr || (t = { _e: [], ready: function (f) { t._e.push(f) } });
}(document, "script", "twitter-wjs"));
</script>    
Run Code Online (Sandbox Code Playgroud)

我把JS写得很漂亮....

function creditTweet() {
  $.post(
    "/credit_tweet",
    {},
    function(result) {
      var text;
      if (result.status === "noop") {
        text = "Thanks for sharing already!";
      } else if (result.status === "ok") {
        text = "5 Kredit Added";
      }
      $("#credited").html(text);
    }
  );
}

$(function() {
  twttr.ready(function (twttr) {
    window.twttr.events.bind('tweet', creditTweet);
  }); 
});
Run Code Online (Sandbox Code Playgroud)

现在问题出在控制器或路由中(我发布的地方).我认为路由很好,因为POST几乎正常工作,因为这是维基百科上的错误描述 - "422 Unprocessable Entity(WebDAV; RFC 4918)请求格式正确但由于语义错误而无法遵循".

那么,你们在控制器中看到我的ruby代码有什么问题吗?

class SocialKreditController < ApplicationController
    TWEET_CREDIT_AMOUNT = 5

  def credit_tweet
    if !signed_in?
      render json: { status: :error }
    elsif   current_user.tweet_credited
        Rails.logger.info "Not crediting #{ current_user.id }"
        render json: { status: :noop }
      else
        Rails.logger.info "Crediting #{ current_user.id }"
        current_user.update_attributes tweet_credited: true
        current_user.add_points TWEET_CREDIT_AMOUNT
        render json: { status: :ok }
      end
  end
end
Run Code Online (Sandbox Code Playgroud)

在我的routes.rb中,它非常直接,所以我怀疑这里有什么不对...

  get 'social_kredit/credit_tweet'
  post '/credit_tweet' => 'social_kredit#credit_tweet'
Run Code Online (Sandbox Code Playgroud)

哪里哦这个错误在哪里?我显然不知道有关HTTP请求的信息.

pir*_*one 54

我搞定了!

我加了......

skip_before_action :verify_authenticity_token
Run Code Online (Sandbox Code Playgroud)

到控制器.

检查日志并发现无法验证CSRF令牌时发现了该问题.

  • 您可能还想查看[此问题](http://stackoverflow.com/questions/7203304/warning-cant-verify-csrf-token-authenticity-rails)以获取不需要禁用csrf令牌的解决方案校验. (10认同)
  • @piratetone:是的,这个原因就是安全. (8认同)
  • [rails安全指南](http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf)很好地解释了csrf.通常,您不应在没有充分理由的情况下禁用csrf检查(例如,来自第三方API的回调).在这种情况下,让csrf检查开心是完全有能力的,这是最好的事情. (4认同)
  • 关闭安全性是解决方案吗? (2认同)

bar*_*lop 5

ihaztehcodez(他最后一次活跃是在 2016 年,所以它无助于推动他发布答案)提到该skip_before_action :verify_authenticity_token技术不是那么安全,因为你失去了伪造保护。

他们提到了最好的/安全的/“更好的做法”,这里提到了解决方案警告:无法验证 CSRF 令牌的真实性

例如

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});
Run Code Online (Sandbox Code Playgroud)

或者

$.ajax({ url: 'YOUR URL HERE',
  type: 'POST',
  beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
  data: 'someData=' + someData,
  success: function(response) {
    $('#someDiv').html(response);
  }
});
Run Code Online (Sandbox Code Playgroud)

或者

把它放在一个ajax请求中

headers: {
  'X-Transaction': 'POST Example',
  'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
Run Code Online (Sandbox Code Playgroud)