Java HttpClient和Devise身份验证问题

3
我正在一个 Web 服务器上运行 devise,并尝试让 Java 应用程序进行身份验证。在应用程序经过身份验证之后,devise 应授权该应用程序在 Web 服务器上创建和更新记录。
我正在查看 Rails 服务器日志,以比较 Web 表单提交的内容与我的应用程序提交的内容。以下是不同的输出结果:
Web 表单(正常工作):
参数:{"utf8"=>"Γ£ô", "authenticity_token"=>"vYC9qd0dVIUH7B/wCHW59JwZquX4yaiogXZ32pbn1So=", "user"=>{"username"=>"user", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
应用程序(不起作用):
参数:{"utf8"=>"?", "username"=>"user", "password"=>"[FILTERED]", "commit"=>"Sign in"}
这是我的应用程序代码。
    public void webLogin(String methodName, String username, String password) {        
        httpPost = new HttpPost(webServiceUrl+methodName);

        try {
            // Add your data
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("utf8", Character.toString('\u2713')));
            nameValuePairs.add(new BasicNameValuePair("username", username));
            nameValuePairs.add(new BasicNameValuePair("password", password));
            nameValuePairs.add(new BasicNameValuePair("commit", "Sign in"));
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            // Execute HTTP Post Request
            HttpResponse response = httpClient.execute(httpPost);

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
        } catch (IOException e) {
            // TODO Auto-generated catch block
        }
    }

明显的区别在于用户名和密码嵌套在用户结构中。那么我的问题是,我该如何创建这个结构呢?
编辑HTTP头信息。
    Request URL:http://localhost:3000/users/sign_in
    Request Method:POST
    Status Code:302 Found
    Request Headersview source
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:en-US,en;q=0.8
    Cache-Control:max-age=0
    Connection:keep-alive
    Content-Length:197
    Content-Type:application/x-www-form-urlencoded
    Cookie:_WebApp_session=BAh7CEkiCmZsYXNoBjoGRUZvOiVBY3Rpb25EaXNwYXRjaDo6Rmxhc2g6OkZsYXNoSGFzaAk6CkB1c2VkbzoIU2V0BjoKQGhhc2h7BjoKYWxlcnRUOgxAY2xvc2VkRjoNQGZsYXNoZXN7BjsKSSIfSW52YWxpZCBlbWFpbCBvciBwYXNzd29yZC4GOwBUOglAbm93bzokQWN0aW9uRGlzcGF0Y2g6OkZsYXNoOjpGbGFzaE5vdwY6C0BmbGFzaEAHSSIPc2Vzc2lvbl9pZAY7AEZJIiU4ODVjM2QxNmNkMTI4YWYxN2E5YzEyNmRjYWI1OTI1YgY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFNVkV4aFNoSnZsQmhxRUFVdjZtZ0ZBblNVQzJjbU1Kb0l3N1U1OHErNUlVPQY7AEY%3D--8b8a1fcee6c194b938781fa60ddb3a91b1ac8c7c
    Host:localhost:3000
    Origin:http://localhost:3000
    Referer:http://localhost:3000/users/sign_in
    User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7
    Form Dataview URL encoded
    utf8:✓
    authenticity_token:MVExhShJvlBhqEAUv6mgFAnSUC2cmMJoIw7U58q 5IU=
    user[username]:user
    user[password]:password
    user[remember_me]:0
    commit:Sign in
    Response Headersview source
    Cache-Control:no-cache
    Connection:Keep-Alive
    Content-Length:88
    Content-Type:text/html; charset=utf-8
    Date:Thu, 26 Jan 2012 03:57:57 GMT
    Location:http://localhost:3000/
    Server:WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
    Set-Cookie:_WebApp_session=BAh7CUkiCmZsYXNoBjoGRUZvOiVBY3Rpb25EaXNwYXRjaDo6Rmxhc2g6OkZsYXNoSGFzaAk6CkB1c2VkbzoIU2V0BjoKQGhhc2h7ADoMQGNsb3NlZEY6DUBmbGFzaGVzewY6C25vdGljZUkiHFNpZ25lZCBpbiBzdWNjZXNzZnVsbHkuBjsAVDoJQG5vd286JEFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hOb3cGOgtAZmxhc2hAB0kiD3Nlc3Npb25faWQGOwBGSSIlYmZkMDkwNDA1ZGZkN2JmZTA1OWM0MDNmZDIxYzU1ODMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxTVZFeGhTaEp2bEJocUVBVXY2bWdGQW5TVUMyY21NSm9JdzdVNThxKzVJVT0GOwBGSSIZd2FyZGVuLnVzZXIudXNlci5rZXkGOwBUWwhJIglVc2VyBjsARlsGaQciIiQyYSQxMCR0b0tHc0FJTWpHRXQxSXp1aWVCRlBl--9e1e39fb97a4452e3693c65cc5f1ac4ad9855c37; path=/; HttpOnly
    X-Runtime:0.231013
    X-Ua-Compatible:IE=Edge

网页请求是什么样子的?我认为HTTP没有发送那样的对象的方法,我怀疑ror有一些识别某些字符串作为序列化对象的方式。 - user684934
我发布的是你要求的内容吗,bdares? - david
2个回答

2

根据目前请求的类型,我建议尝试以下操作:

nameValuePairs.add(new BasicNameValuePair("authenticity_token", myToken));
nameValuePairs.add(new BasicNameValuePair("user[username]", username));
nameValuePairs.add(new BasicNameValuePair("user[password]", password));
nameValuePairs.add(new BasicNameValuePair("user[remember_me]", 0));
nameValuePairs.add(new BasicNameValuePair("commit", "Sign in"));

哈,我发誓我试过了!它起作用了,谢谢你让我在尝试中变得勤奋。 - david

0

我认为在进行POST请求时,您还需要发送您的authenticity_token

"authenticity_token"=>"vYC9qd0dVIUH7B/wCHW59JwZquX4yaiogXZ32pbn1So="

authenticity_token是什么?

当用户查看创建、更新或删除资源的表单时,Rails应用程序会创建一个随机的authenticity_token,将此令牌存储在会话中,并将其放置在表单中的隐藏字段中。当用户提交表单时,Rails会查找authenticity_token,将其与存储在会话中的令牌进行比较,如果它们匹配,则允许请求继续。

在最后一行中,它说“如果它们匹配,则允许请求继续。”但是当您从Java代码进行POST请求时,这种情况并没有发生。


我知道这是个问题,但我目前已经禁用了CSRF。在application_controller.rb中,“protect_from_forgery”被注释掉了。所以,我不认为这是问题的原因。 - david
处理Cookie时,您需要使用Java内置的cookie类或查看http-client文档以获取有关Cookie/会话处理和管理的信息。 - RanRag
我不是Rails专家,但在这篇文章中提到了一种不同的方式来删除auth_token。 - RanRag
我按照那篇帖子的建议添加了config.action_controller.allow_forgery_protection = false。这确实在使用Web表单时删除了真实性令牌,但Java应用程序仍无法进行身份验证。 - david
好的。您可以尝试两件事情:1)在httpheader信息中有一个“Set-Cookie”,请尝试通过您的Java代码发送它,并尝试设置用户代理字符串。 - RanRag
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接