本来有点不太想写这篇文章,原因是写了这个,就感觉WEB应用怎么都可以自己写代码访问内部的资源信息!不过出于技术本身的我还是考虑些点点东西,而且即使我不写,这玩意也有,呵呵,前面一篇文章我提及到双方要约定token来进行认证交互等等,如果你想访问某个网站内部的资源,而且是需要登录的,但是又想通过本地程序直接蹦进去,怎么蹦呢?
办法不是没有,其实httpclient就是模拟一个浏览器的功能,而登录的动作其实就是获取到你的cookie,而httpclient本身有记录cookie的功能,所以这并不难。
也就是说,你要用httpclient来模拟一个网站的登录,然后后续的操作;那么你只需要到那个网站的登录页面中找到用户名和密码的标签的name值,以及其action的目标地址,将其在本地开始进行模拟,标签,并类似于上一篇文章中编写用户名和密码并向action的目标地址发起的post操作(注意这里的POST应该是绝对路径,而不是页面看到的相对路径),此时你就能获取到你的cookie了;
那么登录OK了,cookie获取到了,如何保存cookie呢?其实你根本不用保存,因为httpclient已经帮你保存了,接下来所有的动作,只需要你使用同一个httpclient对象,它们的cookie就是一致的,可以通过同一个httpclient对象发起多次POST或GET请求,这个时候内部想要请求什么就请求什么了。
貌似本文就结束了,要这么简单,我也不会专门抽出来写了,其实上述方法只能适合于一般的普通网站,如果网站的认证方法是https的,也就是你看到它的登录界面是https开头的,那就不行了因为协议不一样了,不过也是有办法的,这也是本文需要阐述的重点,要做这个工作,httpcleint请换成4以上的版本,对应到的包有:commons-httpclient-4.1.3.jar以及httpclient-4.1.2.jar两个包不是一样的内容,在这里这两个包都需要(注意一下代码为非U盾认证方式,U盾认证需要其他的代码来支持)。
加上了这两个包后,在程序开始部分import的内容应该包含:
import org.apache.http.HttpEntity; 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.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; 如果你有什么包引入不进来,说明你找的包还不对。 public class HttpsTest1 { /** * SSL部分的处理 * @param httpClient * @throws NoSuchAlgorithmException * @throws KeyManagementException */ private static void securityProcess(DefaultHttpClient httpClient) throws NoSuchAlgorithmException, KeyManagementException { TrustManager easyTrustManager = new X509TrustManager() { public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {} public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {} public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } }; SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, new TrustManager[]{easyTrustManager}, null); SSLSocketFactory sf = new SSLSocketFactory(sslcontext); Scheme sch = new Scheme("https", 443, sf); httpClient.getConnectionManager().getSchemeRegistry().register(sch); } /** * 处理登录 * @param httpClient * @throws UnsupportedEncodingException * @throws IOException * @throws ClientProtocolException */ private static void login(DefaultHttpClient httpClient) throws UnsupportedEncodingException, IOException,ClientProtocolException { HttpPost httppost = new HttpPost("https://www.xxx.xxx.com/login/");//这是用户名和密码提交的目标路径 List<NameValuePair> params=new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("id",MyUserInfo.USER_NAME));//写入用户名 params.add(new BasicNameValuePair("pass_word",MyUserInfo.PASSWORD));//写入密码 httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8)); HttpResponse response = httpClient.execute(httppost); HttpEntity entity = response.getEntity(); String content = EntityUtils.toString(entity); System.out.println(content); } public static void main(String[] args) throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); try { securityProcess(httpClient); login(httpClient); //以下是你要请求其他的URL HttpGet get = new HttpGet("http://www.xxx.xxx.com/xxx/xxx"); HttpResponse response2 = httpClient.execute(get); System.out.println(EntityUtils.toString(response2.getEntity())); }finally { httpClient.getConnectionManager().shutdown(); } } }
OK。代码细节上我不想多说,不过这段代码去请求一个https的登录是绝对没有问题的,可以将相应的URL换成自己系统的,再试一试!虽然是这个功能,不过,我个人还是不建议这样做,这样做太张扬了,这里仅仅为简单探讨下,可以用它写点程序实现远程系统的本地自动化处理步骤。
另外验证码需要一些解析程序,相对较为复杂,而且可能解析会有问题,对这类问题我也不想研究太多,呵呵,本文说提及的这个程序也和验证码无关。