HttpURLConnection、HttpClient和Session

原文地址:http://www.cnblogs.com/kross/p/3615695.htmlphp

 

一直没弄懂Session,cookies什么的登录验证究竟是怎么回事,昨天分别用HttpURLConnection和HttpClient两个类来实验了一下,基本弄明白了Session验证登录的机制和这两个类的区别。html

第一步:先在本地写一个登录页面和一个内容页面(登录了才能进去)吧。代码大体以下:chrome

下面是login.php,用于请求登录的,经过post传递参数,若是登录成功就会注册session。浏览器

 1 <?php
 2 session_start();
 3 
 4 if (isset($_POST['username'])) {
 5     $username = $_POST['username'];
 6     $password = $_POST['password'];
 7     
 8     if ($username == 'admin' && $password == 'admin') {
 9         $_SESSION['username'] = $username;
10         echo "<a href='content.php'>进入网站</a>";
11     } else {
12         echo "-1";
13     }
14 }
15 ?>
16 <html>
17 <body>
18 <form action="" method="post">
19 <input type="text" name="username" />
20 <input type="password" name="password" />
21 <input type="submit" name="submit" value="submit" />
22 </form>
23 </body>
24 </html>

下面是content.php,会验证session,用来当网站的内容页,登录了才能看到正确的内容。服务器

<?php
session_start();
if (isset($_SESSION['username'])) {
    echo "login ok";
} else {
    echo "not login";
}
?>

接下来先讲HttpURLConnection这个类,先使用这个类直接请求content.php页面,理所应当的返回了"-1"。若是先用这个类去请求login.php,并传递正确的参数,就会显示登录成功,这个时候再去用这个类请求content.php,依然是返回"-1",很显然,HttpURLConnection并无记录咱们登录的状态,或者说服务器认识刚刚登录成功的人,但此次请求content.php的人它依然不认识。这就说明了HttpURLConnection的每一次请求都是独立的,都是一次新的请求,或者说每一次请求都是一个新的会话(session)。cookie

而后我就用chrome去开我本身写的那个测试的网页,发如今同一个网站下,同一次会话中,有一个sessionid是不会变的。网络

就是上面这个东西,若是开着某个页面,不管如何刷新,或者跳转到这个服务器下的其余网站,这个SESSIONID的值都不会改变,可是若是关掉这个服务器下的全部页面,再从新打开这样的一个页面,这个SESSIONID的值就被从新生成了。session

 

因而用HttpURLConnection的状况,第一次登录login.php是一个SESSIONID,确实登录成功了,服务器记住的是SESSIONID为A的状况(假设是A好了),但再去请求content.php的时候,SESSIONID就不是A了,服务器就认为你没有登录,因而就显示了“-1”。问题搞明白了,那么只须要在HttpURLConnection请求的时候,给它加上SESSIONID这个头部就好了。最终代码以下:app

public class NetHelper {
    
    /**
     * SESSIONID
     * */
    private String sessionId = "";
    
    /**
     * 发送一条请求,将内容以字符串返回
     * @param url 请求的地址
     * @return 返回的内容
     * */
    public String request(String url) throws IOException {
        URL uUrl = new URL(url);
        HttpURLConnection huc = (HttpURLConnection) uUrl.openConnection();
        huc.addRequestProperty("Cookie", sessionId);    //为何是“Cookie”,Chrome打开F12本身看看就明白了
        huc.connect();
        BufferedReader br = new BufferedReader(new InputStreamReader(huc.getInputStream()));
        String data = "";
        String line = "";
        while ((line = br.readLine()) != null) {
             data = data + line;
        }
        return data;
    }
    
    /**
     * 发送登录请求,并将SESSIONID保存起来
     * @param url 登录请求的地址
     * @return 返回的内容
     * */
    public String login(String url) throws IOException {
        URL uUrl = new URL(url);
        HttpURLConnection huc = (HttpURLConnection) uUrl.openConnection();
        
        //设置请求方式
        huc.setRequestMethod("POST");
        
        //设置post参数
        StringBuffer params = new StringBuffer();
        params.append("username=").append("admin").append("&").append("password=").append("admin");
        byte[] bytes = params.toString().getBytes();
        huc.getOutputStream().write(bytes);
        
        huc.connect();
        
        //从headers中取出来,并分割,为何要分割,Chrome打开F12本身看看就明白了
        String[] aaa = huc.getHeaderField("Set-Cookie").split(";");
        sessionId = aaa[0];
        
        BufferedReader br = new BufferedReader(new InputStreamReader(huc.getInputStream()));
        String data = "";
        String line = "";
        while ((line = br.readLine()) != null) {
             data = data + line;
        }
        return data;
    }
}

 

接下来就是使用HttpClient,代码相似的,我作了相同的实验,结果就直接出来了,HttpClient会自动的管理Session,第二次请求不须要手动去设置Session就能够登陆上。dom

public class NetClient {
    
    private HttpClient client = null; 
    
    public NetClient() {
        client = new DefaultHttpClient();
    }
    
    public String request(String url) throws ClientProtocolException, IOException {
        HttpPost post = new HttpPost(url);
        HttpResponse res = client.execute(post);
        
        BufferedReader br = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
        String data = "";
        String line = "";
        while ((line = br.readLine()) != null) {
             data = data + line;
        }
        return data;
    }
    
    public String login(String url) throws ClientProtocolException, IOException {
        HttpPost post = new HttpPost(url);
        
        //设置post参数的方式还真是不人性化啊……
        ArrayList<NameValuePair> pa = new ArrayList<NameValuePair>();
        pa.add( new BasicNameValuePair( "username", "admin"));
        pa.add( new BasicNameValuePair( "password", "admin"));
        post.setEntity( new UrlEncodedFormEntity(pa, "UTF-8"));

        HttpResponse res = client.execute(post);
        
        BufferedReader br = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
        String data = "";
        String line = "";
        while ((line = br.readLine()) != null) {
             data = data + line;
        }
        return data;
    }
}

最后总结一下,Session验证的方式是在一次会话中,为每个客户端都生成了一个SESSIONID,若是是成功登录的,服务器端就会记录好,登录成功的SESSIONID,若是登录失败或者新的SESSIONID,都将没法验证登录,这就是SESSION验证登录的基本状况。

而HttpURLConnection和HttpClient这两个类均可以用来网络请求,但稍有不一样,HttpuRLConnection每一次请求都是新的会话,若是须要去验证SESSIONID,就必须手动的去设置Header,HttpClient就能智能的管理Session,不须要手动设置,实际上HttpClint就相似于一个程序中的小浏览器。

 

最大的槽点我以为就是这两个类设置post参数的方式都很2B一点都不方便……

 

另外HttpClient不能同时发送两次请求,若是一个请求尚未结束或者关闭,又立刻开启另外一个请求。就会报警告,截个图吧

 

因此我综合考虑了下,之后仍是尽可能都使用HttpURLConnection吧……

 

原文地址:http://www.cnblogs.com/kross/p/3615695.html

新浪微博:http://weibo.com/KrossFord

相关文章
相关标签/搜索