2013年2月6日星期三

Android HTTP session && cookie



HTTP协议与状态保持
HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。
   
    然而聪明(或者贪心?)的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求,作为传输载体的HTTP协议也添加了文件上载、cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。
   
    让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:
    1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
    2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。
    3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。
   
    由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

Cookie 定义




 1 typedef struct CookieEntry
 2 {
 3        PTCHAR     pszName;
 4        PTCHAR     pszValue;
 5        PTCHAR     pszUrlPath;
 6        DWORD      dwFlags;//Security Flags
 7        DWORD      dwLowWordExpiration;//LowWord of FILETIME
 8        DWORD      dwHighWordExpiration;//HighWord ofFILETIME
 9        DWORD      dwLowWordCreation;//LowWord of FILETIME
10        DWORD      dwHighWordCreation;//HighWord of FILETIME
11        CHAR   chEnd;//'*'
12 }COOKIEENTRY, *LPCOOKIEENTRY;



总结起来,每个Cookie有6个属性,分别 为:Cookies Name; Cookies Value; Domain;Path; Secure; Expire Date。这里给出的Cookie的6个属性和C++中定义的结构体不完全一致。其原因将在Cookie的文件格式小节给出解释。
下面对Cookie结构中的各个属性分别给出解释:
Cookies Name <Key>, 必要属性,指明了Cookie的名字,有一系列字符(不包括括号、逗号、空格等)组成;每个cookie由一个唯一的名称代表,这个名称可以包含字母、数 字、下划线。Cookie的名称是不分大小写,所以mycookie和MyCookie是一样。但考虑到服务器端语言可能区分大小写,所以对程序开发者来 说定义和使用时最好还是区分大小写。
Cookies Value,<Value>Cookie 的值,Web服务器储存在Cookie中的信息;保存在Cookie中的字符串值。这个值在存储之前是用encodeURIComponent()对其进 行编码的,否则会丢失数据或占用了Cookie。而且Cookie名字和值加起来的字节数不能超过4095字节,也即4KB。
Domain, 可选,指明了Cookie的有效域的范围,默认的是产生Cookie的服务器的名字;出于安全考虑,网站不能访问由其他域所创建的Cookie。创建 Cookie以后,域的信息会作为cookie的一部分存储下来。关于域,举个例子来说,如http://www.baidu.com/view /index.html, 它的域为:baidu.com。这里不做详述,后面的章节会有所涉及。
Path, 可选,指明了Cookie在有效域中的有效路径,在有效路径外的网页不可以读写Cookie,默认的是产生此Cookie的信息的URL;而该属性也是 Cookie的另一个安全特征,限制对Web服务器上特定目录的访问。即控制哪些访问能触发发送。例如请求的地址是上面的URL,如果 path=/view,这个Cookie就会被发送,但是path为其他路径的话,该Cookie会被忽略。
Secure, 可选,一个true/false值,用于表示Cookie是否只能从安全网站(使用SSL和https协议的网站)中访问;即如果标记一个Cookie为 安全的(这个值被设置为true),那么仅当客户端与服务器的对话通道是安全的(如HTTP over SSL),Cookie才会被传送。
Expire Date, 可选,指明了Cookie的有效时间,一旦过期,Cookie将不再有效,通常由产生Cookie的程序(Date由服务器指明)指定,如果不指明,系统会默认Cookie将在用户会话结束后自动过期。



cookie机制和session机制的区别
*************************************************************************************
Cookie是客户端的存储空间,由浏览器来维持。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制("PHPSESSID")来达到保存标识的目的,但实际上还有其他选择,比如说重写URL和隐藏表单域。
如何利用实现自动登录
*************************************************************************************
当用户在某个网站注册后,就会收到服务器发送的一个惟一用户ID的cookie。客户后来重新连接时,这个用户ID会自动发送回服务器,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。
如何根据用户的爱好定制站点
*************************************************************************************
网站可以使用cookie记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用户,由服务器端的数据库存储每个标识符对应的页面设置。

通过Cookie实现Session保持




1.import java.io.IOException;

2.import java.io.UnsupportedEncodingException;

3.import java.util.List;

4.

5.import org.apache.http.HttpEntity;

6.import org.apache.http.HttpResponse;

7.import org.apache.http.HttpStatus;

8.import org.apache.http.NameValuePair;

9.import org.apache.http.client.ClientProtocolException;

10.import org.apache.http.client.CookieStore;

11.import org.apache.http.client.entity.UrlEncodedFormEntity;

12.import org.apache.http.client.methods.HttpPost;

13.import org.apache.http.cookie.Cookie;

14.import org.apache.http.impl.client.DefaultHttpClient;

15.import org.apache.http.protocol.HTTP;

16.import org.apache.http.util.EntityUtils;

17.

18.public class MyHttpClient implements InetConfig {

19.private DefaultHttpClient httpClient;

20.private HttpPost httpPost;

21.private HttpEntity httpEntity;

22.private HttpResponse httpResponse;

23.public static String PHPSESSID = null;

24.public LVHttpClient() {

25.

26.    }

27.

28.public String executeRequest(String path, List<NameValuePair> params) {

29.        String ret = "none";

30.       try {

31.            this.httpPost = new HttpPost(BASEPATH + path);

32.            httpEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8);

33.            httpPost.setEntity(httpEntity);

34.             //第一次一般是还未被赋值,若有值则将SessionId发给服务器

35.            if(null != PHPSESSID){

36.                httpPost.setHeader("Cookie", "PHPSESSID=" + PHPSESSID);

37.            }

38.            httpClient = new DefaultHttpClient();

39.        } catch (UnsupportedEncodingException e) {

40.            e.printStackTrace();

41.        }

42.        try {

43.            httpResponse = httpClient.execute(httpPost);

44.            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

45.                HttpEntity entity = httpResponse.getEntity();

46.                ret = EntityUtils.toString(entity);

47.                CookieStore mCookieStore = httpClient.getCookieStore();

48.                List<Cookie> cookies = mCookieStore.getCookies();

49.                for (int i = 0; i < cookies.size(); i++) {

50.                     //这里是读取Cookie['PHPSESSID']的值存在静态变量中,保证每次都是同一个值

51.                     if ("PHPSESSID".equals(cookies.get(i).getName())) {

52.                        PHPSESSID = cookies.get(i).getValue();

53.                        break;

54.                    }

55.

56.                }

57.            }

58.        } catch (ClientProtocolException e) {

59.            e.printStackTrace();

60.        } catch (IOException e) {

61.            e.printStackTrace();

62.        }

63.        return ret;

64.    }

65.}



基于http协议的,那么如果网站不是php做的话,那个叫做Sessionid的Cookie可能叫做别的了,就不是PHPSESSID了,而是叫做别的名字了,这个可能要具体情况去查

没有评论:

发表评论