rails3.1 的link_to中delete无效的问题解决
现在才开始rails之旅有点晚,最近在捣鼓,发现变化确实很大,下面遇到的众多问题中的一个:
link_to 删除的操作无法正常进行,就是下面这行代码
<%= link_to "删除", article_path(article.id), :method => :delete, :confirm=>"are you sure?" %>
在rails2上没有任何问题,在用默认的prototype那一系列的js也可能没问题,关键是我卸载来prototype,安装的jquery。
首先是 点击 删除 链接之后,跳到了show页面,完全没有弹出框提示,造成这个问题的原因是一个低级错误,jquery的js文件没有引入
<%= javascript_include_tag "jquery.min" %><%= javascript_include_tag "jquery_ujs" %>(这个文件是关键)
引入之后弹出框生效来(说明生成的html代码中的自定义属性被解析来),但是删除仍然是无法进行,日志中显示了下面这一句提示:
WARNING: Can't verify CSRF token authenticity
先前,我曾经把link_to改成button_to,这个是完全可以操作的,button_to的原理是生成一个form表单,这个表单是自带token authenticity,这里 token authenticity 的警告正好说明link_to所缺少的东西,我的destroy action要经过一个登录验证,每次点击删除都是进入登录页面,误导我因为哪里的代码写错了删除来session,检查代码无误后,才明白是token authenticity的问题。
添加这一行代码到layout中
<%= csrf_meta_tag %>
解析生成的html代码如下:
<meta content="authenticity_token" name="csrf-param"><meta content="wItbwqqVKfksJM4XuF8JteFBpSMhgr3IRYWLCmyXi2c=" name="csrf-token">
这个就完全解决了,删除操作提交的token问题
关于token的问题,在stackflow有一个很好的解释
http://stackoverflow.com/questions/941594/understand-rails-authenticity-token
原文贴出来:
引用What happens: When the user views a form to create, update, or destroy a resource, the rails app would create a random authenticity_token, store this token in the session, and place it in a hidden field in the form. When the user submits the form, rails would look for the authenticity_token, compare it to the one stored in the session, and if they match the request is allowed to continue.
Why this happens: Since the authenticity token is stored in the session, the client can not know its value. This prevents people from submitting forms to a rails app without viewing the form within that app itself. Imagine that you are using service A, you logged into the service and everything is ok. Now imagine that you went to use service B, and you saw a picture you like, and pressed on the picture to view a larger size of it. Now, if some evil code was there at service B, it might send a request to service A (which you are logged into), and ask to delete your account, by sending a request to http://serviceA.com/close_account. This is what is known as CSRF (Cross Site Request Forgery).
If service A is using authenticity tokens, this attack vector is no longer applicable, since the request from service B would not contain the correct authenticity token, and will not be allowed to continue.
Notes: Keep in mind, rails only checks POST, PUT, and DELETE requests. GET request are not checked for authenticity token. Why? because the HTTP specification states that GET requests should NOT create, alter, or destroy resources at the server, and the request should be idempotent (if you run the same command multiple times, you should get the same result every time).
Lessons: Use authenticity_token to protect your POST, PUT, and DELETE requests. Also make sure not to make any GET requests that could potentially modify resources on the server.