use*_*893 6 java j-security-check form-authentication apache-httpclient-4.x
我正在尝试使用Apache HttpClient Java库对使用基于表单的身份验证(例如,facebook.com)的网站进行身份验证.
使用这个网站的程序作为一个主要的例子:http://www.elitejavacoder.com/2013/10/http-client-form-based-authentication.html,我能够做到 - 但有一些事情,我我不理解这个节目.这是代码:
package com.elitejavacoder.http.client;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class HttpClientFormAuthentication {
public static void main(String[] agrs) {
String host = "yourhostname.com";
int port = 8080;
String protocol = "http";
DefaultHttpClient client = new DefaultHttpClient();
try {
HttpHost httpHost = new HttpHost(host, port, protocol);
client.getParams().setParameter(ClientPNames.DEFAULT_HOST, httpHost);
HttpGet securedResource = new HttpGet("/secured/index.jsp");
HttpResponse httpResponse = client.execute(securedResource);
HttpEntity responseEntity = httpResponse.getEntity();
String strResponse = EntityUtils.toString(responseEntity);
int statusCode = httpResponse.getStatusLine().getStatusCode();
EntityUtils.consume(responseEntity);
System.out.println("Http status code for Unauthenticated Request: " + statusCode);// Statue code should be 200
System.out.println("Response for Unauthenticated Request: \n" + strResponse); // Should be login page
System.out.println("================================================================\n");
HttpPost authpost = new HttpPost("/j_security_check");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("j_username", "yourusername"));
nameValuePairs.add(new BasicNameValuePair("j_password", "yourpassword"));
authpost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpResponse = client.execute(authpost);
responseEntity = httpResponse.getEntity();
strResponse = EntityUtils.toString(responseEntity);
statusCode = httpResponse.getStatusLine().getStatusCode();
EntityUtils.consume(responseEntity);
System.out.println("Http status code for Authenticattion Request: " + statusCode);// Status code should be 302
System.out.println("Response for Authenticattion Request: \n" + strResponse); // Should be blank string
System.out.println("================================================================\n");
httpResponse = client.execute(securedResource);
responseEntity = httpResponse.getEntity();
strResponse = EntityUtils.toString(responseEntity);
statusCode = httpResponse.getStatusLine().getStatusCode();
EntityUtils.consume(responseEntity);
System.out.println("Http status code for Authenticated Request: " + statusCode);// Status code should be 200
System.out.println("Response for Authenticated Request: \n" + strResponse);// Should be actual page
System.out.println("================================================================\n");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我有以下问题(我将要引用的行号在上面提供的链接的上下文中,因为StackOverflow不允许包含行号):
究竟什么是"/ j_security_check"(第41行)?作者是如何知道他必须使用"j_security_check"而不是安全资源的名称?
为什么字符串"strResponse = EntityUtils.toString(responseEntity);" (第49行),这是"httpResponse = client.execute(authpost);"之后的两行; (第47行),不同于字符串"strResponse = EntityUtils.toString(responseEntity);" (第59行),这是"httpResponse = client.execute(securedResource);"之后的两行.(第57行)?
基本上,第47和57行之间的"客户"发生了什么变化?
谢谢
这/j_security_check是一个表单操作,以便容器知道此请求用于身份验证,容器处理该请求./j_security_check是用于提交特定于Enterprise Java应用程序服务器的身份验证表单的网页地址.
j_username并且j_password是要提交用户名和密码的请求参数的名称.这三个应该以这样的方式来命名(即j_security_check,j_username并且j_password使容器处理该请求作为认证请求,它可以检索从提交的请求所需要的信息(如用户名和密码)).
作者知道他/她需要使用,/j_security_check因为他/她假设他正在对J2EE应用服务器进行身份验证.这不是一个很好的假设.请注意,端口设置为8080?这是Java服务器(如Tomcat)通常使用的端口,因此它们不会与HTTP服务器上的端口80发生冲突.
strResponse第47行包含登录请求本身的内容(什么都不是),strResponse第57行包含安全页面的内容.这是细分:
如果您在Web浏览器中执行此操作,则会发生以下情况.
第31行是未经身份验证的初始页面访问.第38-39行显示登录表单,第41-45行相当于在表单中键入用户名和密码.
第47行就像点按"提交"按钮.
第49行显示了服务器响应发送的内容.请注意第54行中的注释是"应为空字符串".提交用户名和密码时,响应中最关心的是HTTP状态.打印出状态代码的行中的注释显示"状态代码应为302".302是HTTP状态,告诉浏览器重定向.响应标头将包含您的浏览器重定向到的地址.响应标头还包含身份验证cookie.如果打印出来也会很好,这将有助于理解这一切是如何工作的.代码是在第57行手动执行重定向,但它假设它将被重定向到它尝试在第31行访问的安全页面,而不是从HTTP响应头中检索该地址.
最大的变化client是第57行client具有身份验证cookie,类似于浏览器操作.DefaultHttpClient处理所有这些问题.
身份验证cookie以Set-Cookie HTTP标头的形式来自服务器.这告诉client存储cookie.然后,在发出请求时,客户端会发送Cookie HTTP标头以及cookie数据.
在client最初接收在包含登录表单,它存储的响应的cookie中.当client发送回填写的表单时,该cookie也包含在请求中,并且此后每次向服务器发送请求.因此,一旦您进行了身份验证,服务器就会存储该信息并将其与cookie相关联.然后,当后续请求来自时client,服务器会看到cookie并记住您已经过身份验证.在client完成所有浏览器确实给管理与服务器cookie数据传输同样的事情.