发送 HTTP POST 时出现 InvalidAuthenticityToken 异常
我们正在为库存系统项目(针对学校)创建一个 Java 客户端来与 Ruby on Rails 服务器交互。
我们使用的客户端应该执行 HTTP GET 来请求信息,并执行 HTTP POST 来更新或创建新信息(是的,我们知道 HTTP PUT...)。
不幸的是,当我们尝试执行 HTTP post 时,遇到了 InvalidAuthenticityToken 错误。我们通过 HTTP 基本身份验证进行身份验证,我们的控制器如下所示:
class UsersController < ApplicationController
before_filter :authenticate
def show
@user = User.find(params[:id])
#@user = User.all
render :xml => @user.to_xml
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
render :text => 'Success!'
else
render :text => 'No success!'
end
end
private
def authenticate
logger.info("Entering Authen..")
authenticate_or_request_with_http_basic do |username, password|
logger.info("Time: #{Time.now}, username: #{username}, password: #{password}")
User.authenticate(username, password)
end
end
end
show 操作完美运行,并且使用有效的用户名和密码触发身份验证操作(例如,工作正常...)。当我们尝试将更新发布到更新操作时,就会出现问题。当我们尝试它时,我们会收到 InvalidAuthenticityToken 异常。以下内容来自我们的开发日志:
#Successful GET
Processing UsersController#show (for 10.18.2.84 at 2010-11-24 19:02:42) [GET]
Parameters: {"id"=>"2"}
Entering Authen..
Filter chain halted as [:authenticate] rendered_or_redirected.
Completed in 3ms (View: 2, DB: 0) | 401 Unauthorized [http://10.18.2.84/users/show/2]
Processing UsersController#show (for 10.18.2.84 at 2010-11-24 19:02:43) [GET]
Parameters: {"id"=>"2"}
Entering Authen..
Time: Wed Nov 24 19:02:43 -0600 2010, username: admin, password: pass
[4;36;1mUser Load (1.0ms)[0m [0;1mSELECT * FROM "users" WHERE (user_name = 'admin' AND password = 'pass') LIMIT 1[0m
[4;35;1mUser Load (0.0ms)[0m [0mSELECT * FROM "users" WHERE ("users"."id" = 2) [0m
Completed in 18ms (View: 2, DB: 1) | 200 OK [http://10.18.2.84/users/show/2]
#Unsuccessful POST
Processing UsersController#update (for 10.18.2.84 at 2010-11-24 19:03:06) [POST]
Parameters: {"id"=>"2", "first-name"=>"Macky"}
ActionController::InvalidAuthenticityToken
(ActionController::InvalidAuthenticityToken):
我们担心的是,它甚至没有尝试验证基本身份验证 - 据我们所知,它跳过了过滤器和整个控制器。我们的代码在客户端中非常普通(为了便于理解,我们对其进行了编辑):
DefaultHttpClient httpClient = new DefaultHttpClient();
myCredentials = new UsernamePasswordCredentials( username, password );
//Set Provider
provider = new BasicCredentialsProvider();
provider.setCredentials(scope, myCredentials);
//Set Credentials
httpClient.setCredentialsProvider( provider );
ArrayList<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("first-name", "Macky"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
//Set the post
post = new HttpPost( url );
post.setEntity(formEntity);
response = httpClient.execute( post );
那么,我们是在 Rails 中做错了什么,还是在 Java Jakarta 客户端中做错了?非常感谢任何帮助。
We're creating a Java client to interface with a Ruby on Rails server for an inventory system project (for school).
The client that we're using is supposed to do HTTP GET's to request information and HTTP POST's to update or create new information (yes, we know about HTTP PUT...).
Unfortunately, we are running into a InvalidAuthenticityToken error when we try to do a HTTP post. We authenticate through HTTP basic authentication and our controllers look like this:
class UsersController < ApplicationController
before_filter :authenticate
def show
@user = User.find(params[:id])
#@user = User.all
render :xml => @user.to_xml
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
render :text => 'Success!'
else
render :text => 'No success!'
end
end
private
def authenticate
logger.info("Entering Authen..")
authenticate_or_request_with_http_basic do |username, password|
logger.info("Time: #{Time.now}, username: #{username}, password: #{password}")
User.authenticate(username, password)
end
end
end
The show action works perfectly and the authentication action is triggered with a valid username and password (e.g., working fine...). Our problem happens when we attempt to POST an update to the update action. When we attempt it, we get an InvalidAuthenticityToken exception. The following is from our development log:
#Successful GET
Processing UsersController#show (for 10.18.2.84 at 2010-11-24 19:02:42) [GET]
Parameters: {"id"=>"2"}
Entering Authen..
Filter chain halted as [:authenticate] rendered_or_redirected.
Completed in 3ms (View: 2, DB: 0) | 401 Unauthorized [http://10.18.2.84/users/show/2]
Processing UsersController#show (for 10.18.2.84 at 2010-11-24 19:02:43) [GET]
Parameters: {"id"=>"2"}
Entering Authen..
Time: Wed Nov 24 19:02:43 -0600 2010, username: admin, password: pass
[4;36;1mUser Load (1.0ms)[0m [0;1mSELECT * FROM "users" WHERE (user_name = 'admin' AND password = 'pass') LIMIT 1[0m
[4;35;1mUser Load (0.0ms)[0m [0mSELECT * FROM "users" WHERE ("users"."id" = 2) [0m
Completed in 18ms (View: 2, DB: 1) | 200 OK [http://10.18.2.84/users/show/2]
#Unsuccessful POST
Processing UsersController#update (for 10.18.2.84 at 2010-11-24 19:03:06) [POST]
Parameters: {"id"=>"2", "first-name"=>"Macky"}
ActionController::InvalidAuthenticityToken
(ActionController::InvalidAuthenticityToken):
Our concern is that it isn't even attempting to authenticate the basic authentication -- it's skipping the filter and the entire controller as far as we can tell. Our code is pretty vanilla in the client (this is edited down for comprehensibility from what it actually is):
DefaultHttpClient httpClient = new DefaultHttpClient();
myCredentials = new UsernamePasswordCredentials( username, password );
//Set Provider
provider = new BasicCredentialsProvider();
provider.setCredentials(scope, myCredentials);
//Set Credentials
httpClient.setCredentialsProvider( provider );
ArrayList<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("first-name", "Macky"));
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
//Set the post
post = new HttpPost( url );
post.setEntity(formEntity);
response = httpClient.execute( post );
So, is it with Rails that we're doing something wrong or is it with the Java Jakarta client? Any help is greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否在 POST 数据中包含 CSRF 令牌?
请参阅此链接: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection /ClassMethods.html
默认情况下,
protect_from_forgery
处于启用状态,这使得 Rails 需要为任何非 GET 请求提供真实性令牌。 Rails 会自动在使用表单助手创建的表单中包含真实性令牌,但我猜由于您正在构建自己的表单来发布,因此您不会包含令牌。Are you including the CSRF token in your POST data?
See this link: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html
By default
protect_from_forgery
is enabled which makes Rails require an authenticity token for any non-GET requests. Rails will automatically include the authenticity token in forms created with the form helpers but I'm guessing since you're building your own form to post, you're not including the token.