欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

【IOS学习】网络请求中的cookie

程序员文章站 2022-09-04 17:16:05
服务端代码 //设置cookie function cookie(req,res){ //打印客户端的cookie console.log("client c...

服务端代码


    //设置cookie
	function cookie(req,res){
		//打印客户端的cookie
		console.log("client cookie:"+req.headers.cookie);

		var today = new date();
		var time = today.gettime() + 60*1000;
		var time2 = new date(time);
		var timeobj = time2.togmtstring();

        //给f的值添加了一个过期时间的参数
	    res.setheader("set-cookie", ['d=001;maxage=10*1000', 'e=1112', 'f=2222;expires='+timeobj]);

		var msg = { "status":1,"msg":"succeed"}
		res.write(json.stringify(msg));
		res.end();
	}

这段代码主要有2个地方需要注意,一是服务端设置cookie并返回到客户端,一个是服务端获取客户端上传的cookie

服务端设置cookie

服务端设置主要是通过在相应头中设置set-cookie,可以使用response.writehead或是response.setheader方法设置

cookie的设置的一般格式:

单个

    set-cookie:
            cookiename=cookievalue;
            [expires=]
            [;domain=]
            [;path=]
            [;secure=]
            [;httponly=]

多个

    set-cookie:'[cookie1,cookie2];

参数说明:

1、expires:指定过期时间,以gmt格式表示的时间字符串,如方法一个的“timeobj”。
2、maxage:指定过期时间,同expires(expires和maxage选两者其一设值即可)。和expires不同之处在于,maxage值的单位为毫秒(见方法二中的maxage:10*1000,即为10秒)。maxage值可以是正数和负数。正数表示当前cookie存活的时间。负数表示当前cookie只是随着浏览器存储在客户端的内存里,只要关闭浏览器,此cookie就马上消失。默认值为-1。
3、domain:指定可访问cookie的主机名。主机名是指同一个域名下的不同主机。如:www.google.com和gmail.google.com是在两个不同的主机上,即两个不同的主机名。默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问,但可以通过domain参数来实现对其的控制,即所谓的跨子域。以google为例,要实现跨主机(跨子域)访问,写法如下:domain=.google.com,这样就实现了所有google.com下的主机都可以访问此cookie。(本机环境上设置此值时,cookie无法查看。)
4、path:指定可访问此cookie的目录。如:path=/default  表示当前cookie仅能在 default 目录下使用。默认值为“/”,即根目录下的所有目录皆可以访问。
5、secure:当设为true时,表示创建的cookie会以安全的形式向服务器传输,即只能在https连接中被浏览器传递到服务器端进行会话验证;若是http连接则不会传递该信息,所以不会被窃取到cookie里的具体内容。同理,在客户端,我们也无法使用document.cookie找到被设置了secure=true的cookie健值对。secure属性是防止信息在传递的过程中被监听捕获后信息泄漏,httponly属性的目的是防止程序获取cookie后进行攻击(xss)。我们可以把secure=true看成比httponly=true是更严格的访问控制。
6、httponly:是微软对cookie做的扩展。如果在cookie中设置了“httponly”属性,则通过程序(js脚本、applet等)将无法读取到cookie信息,防止xss攻击产生。

服务端设置cookie的例子:

//例子1
res.setheader("set-cookie", ['a=001', 'b=1112', 'c=2222']);

//例子2 设置过期时间
var today = new date();
var time = today.gettime() + 60*1000;
var time2 = new date(time);
var timeobj = time2.togmtstring();
 res.setheader("set-cookie", ['d=001', 'e=1112', 'f=2222;expires='+timeobj,]);

//例子3:
res.writehead(200,{
    'content-type':'text/json',
    "set-cookie":['a=001', 'b=1112', 'c=2222']
});

服务端获取客户端cookie

//打印客户端的cookie
console.log("client cookie:"+req.headers.cookie);

服务端删除或修改cookie

删除和修改cookie本质都是一样的,把原来存在的cookie设为空值,就是删除,设为其他的值就是修改,服务端也有封装好的cookie库, 我们这里的方法都是最底层的htpp模块的方法。

客户端ios 操作cookie


获取服务端返回的cookie


    //获取cookie
    nsdictionary *headers = [((nshttpurlresponse *)resp) allheaderfields];
    nslog(@"headers:%@",headers);
    nsdictionary *cookies = [nshttpcookie cookieswithresponseheaderfields:headers forurl:[nsurl urlwithstring:@"https://localhost/"]];

    for (nshttpcookie *cookie in cookies) {
        nslog(@"cookie:%@",cookie);
    }

服务端返回的cookie在响应头中,请求上节服务端代码设置cookie的那个路径:https://localhost:8001/cookie 后打印的结果如下:

2016-02-13 18:04:08.611 network-demo[20302:1737476] ====请求开始====
2016-02-13 18:04:08.611 network-demo[20302:1737476] {
    msg = succeed;
    status = 1;
}
2016-02-13 18:04:08.611 network-demo[20302:1737476] ====请求结束====
2016-02-13 18:04:08.611 network-demo[20302:1737476] headers:{
    connection = "keep-alive";
    date = "sat, 13 feb 2016 10:04:08 gmt";
    "set-cookie" = "d=001;maxage=10*1000, e=1112, f=2222;expires=sat, 13 feb 2016 10:05:08 gmt";
    "transfer-encoding" = identity;
}
2016-02-13 18:04:08.617 network-demo[20302:1737476] cookie:
2016-02-13 18:04:08.617 network-demo[20302:1737476] cookie:
2016-02-13 18:04:08.617 network-demo[20302:1737476] cookie:

可以看到服务端获取了3个cookie,key分别是d,e,f,其中f设置了cookie的过期时间。

客户端cookie会在每次请求中把cookie自动加载到请求头中发送给服务端, 我们已经收到相应的cookie后,再次请求服务端另一个没有设置cookie的url,看看服务端打印出客户端请求头中的cookie

{ host: 'localhost:8001',
  accept: '*/*',
  cookie: 'd=001; e=1112',
  'user-agent': 'network-demo/1 cfnetwork/758.0.2 darwin/14.5.0',
  'accept-language': 'en-us',
  'accept-encoding': 'gzip, deflate',
  connection: 'keep-alive' }
/
client cookie:d=001; e=1112

可以看到请求头中获取到了cookie:client cookie:d=001; e=1112。 但是这里有个问题,我少了一个key为f的cookie,那是因为f的cookie已经过期了。再看之前ios模拟器打印的过期时间和服务返回的时间有8小时时差,这个应该是 服务端的时间制式和客户端的制式不同导致的吧,已经搞mongodb的时候也遇到过,这里不用纠结这些小问题了,反正就是过期了。

获取客户端存储的cookie

通过nshttpcookiestorage的单例类就可以获取到之前服务端的cookie

//获取本地cookie
nshttpcookiestorage *httpcookiesstorage =  [nshttpcookiestorage sharedhttpcookiestorage];
nsdictionary *cookies = [httpcookiesstorage cookiesforurl:[nsurl urlwithstring:@"https://localhost/"]];
for (nshttpcookie *cookie in cookies) {
    nslog(@"cookie:%@",cookie);
}

客户端设置本地cookie


//客户端设置cookie
-(void)clientsetcookie{

    nsdictionary *prop1 = [nsdictionary dictionarywithobjectsandkeys:
                           @"a",nshttpcookiename,
                           @"aaa",nshttpcookievalue,
                           @"/",nshttpcookiepath,
                           [nsurl urlwithstring:@"https://localhost/"],nshttpcookieoriginurl,
                           [nsdate datewithtimeintervalsincenow:60],nshttpcookieexpires,
                           nil];

    nsdictionary *prop2 = [nsdictionary dictionarywithobjectsandkeys:
                           @"b",nshttpcookiename,
                           @"bbb",nshttpcookievalue,
                           @"/",nshttpcookiepath,
                           [nsurl urlwithstring:@"https://localhost/"],nshttpcookieoriginurl,
                           [nsdate datewithtimeintervalsincenow:60],nshttpcookieexpires,
                           nil];

    nshttpcookie *cookie1 = [nshttpcookie cookiewithproperties:prop1];
    nshttpcookie *cookie2 = [nshttpcookie cookiewithproperties:prop2];

    //单个设置
//    [[nshttpcookiestorage sharedhttpcookiestorage] setcookie:cookie1];
//    [[nshttpcookiestorage sharedhttpcookiestorage] setcookie:cookie2];

    //批量设置
    nsarray *cookies = @[cookie1,cookie2];
    [[nshttpcookiestorage sharedhttpcookiestorage]setcookies:cookies forurl:[nsurl urlwithstring:@"https://localhost/"] maindocumenturl:nil];

    nslog(@"设置完成");
}

说明: - 设置好了之后,下次请求url时会自动带入cookie中的数据 -[nsdate datewithtimeintervalsincenow:60]是设置1分钟后超时 - 可以一个个设置也可以使用setcookies批量设置 - maindocumenturl: the url of the main html document for the top-level frame, if known. can be nil. this url is used to determine if the cookie should be accepted if the cookie accept policy is nshttpcookieacceptpolicyonlyfrommaindocumentdomain

删除cookie

- (void)deletecookie:(nshttpcookie *)cookie;
- (void)removecookiessincedate:(nsdate *)date ns_available(10_10, 8_0);

我们来示范如何删除cookie

    #pragma mark -客户端删除cookie
    //根据url和name删除cookie
    -(void)deletecookie:(nsstring *)cookiename url:(nsurl *)url{
        //根据url找到所属的cookie集合
        nsarray *cookies = [[nshttpcookiestorage sharedhttpcookiestorage]cookiesforurl:url];
        for (nshttpcookie *cookie in cookies) {
            if([cookie.name isequaltostring:cookiename]){
                [[nshttpcookiestorage sharedhttpcookiestorage] deletecookie:cookie];
                nslog(@"删除cookie:%@",cookiename);
            }
        }
    }
    //删除全部cookies
    -(void)deletecookies{
        for (nshttpcookie *cookie in [[nshttpcookiestorage sharedhttpcookiestorage]cookies]) {
            [[nshttpcookiestorage sharedhttpcookiestorage] deletecookie:cookie];
        }
        nslog(@"删除完成");
    }

cookie的本地缓存策略

//设置cookie本地缓存策略
//nshttpcookieacceptpolicyalways:保存所有cookie,这个是默认值
//nshttpcookieacceptpolicynever:不保存任何响应头中的cookie
//nshttpcookieacceptpolicyonlyfrommaindocumentdomain:只保存域请求匹配的cookie

我们测试一下效果:[[nshttpcookiestorage sharedhttpcookiestorage]setcookieacceptpolicy:nshttpcookieacceptpolicynever];

这样设置之后,调用demo中的客户端设置cookie,在调用从服务端获取cookie,最后调用打印客户端cookie,查看日志:


我们可以看到,客户端没有打印任何cookie,因为设置的策略为:nshttpcookieacceptpolicynever

我们在修改为nshttpcookieacceptpolicyalways 或是 nshttpcookieacceptpolicyonlyfrommaindocumentdomain,再次测试一次,可以看到,服务端和客户端设置的cookie都会打印出来。这两个选项会针对不同域名返回的cookie做选择性保存。

2016-02-14 00:59:47.030 network-demo[21191:1810897] cookie:
2016-02-14 00:59:47.030 network-demo[21191:1810897] cookie:
2016-02-14 00:59:47.030 network-demo[21191:1810897] cookie:
2016-02-14 00:59:47.031 network-demo[21191:1810897] cookie:
2016-02-14 00:59:47.031 network-demo[21191:1810897] cookie:

使用cookie的注意点


cookie的性能影响

由于cookie的实现机制,除非cookie过期,否则浏览器每次请求都会向服务器发送cookie,一旦cookie设置过多,会导致请求报头过大,造成带宽的浪费。因此,对cookie的性能优化也是值得关注的一个问题。如何进行性能优化?

  • 减小cookie的大小
  • 为不需要cookie的换个域名,以减少无效cookie的传输
  • 减少dns查询