session是什么

前言:

今天就来彻底的学一些session是个啥东西,我罗列了几个需要知道的要点:

1.session 是啥?
2.怎么保存的?

3.如何运行?

4.有生命周期吗?

5.关闭浏览器会过期吗?

6.Redis代替文件存储session

7.分布式session的同步问题


session是啥?


首先,我大致的知道,session是一次浏览器和服务器的交互的会话,会话是啥呢?就是我问候你好吗?你回恩很好。就是一次会话,那么对话完成后,这次会话就结束了,还有我也知道,我们可以将一个变量存入全部的 $_SESSION['name']中,这样php的各个页面和逻辑都能访问到,所以很轻松的用来判断是否登陆。

这是我之前理解的session,当然也是对的,只是解释的太肤浅,理解的太表面了,面试官如果听到这样的答案其实是不太满意的。我参考了其他的很多资料,彻底理解清楚session。

在说session是啥之前,我们先来说说为什么会出现session会话,它出现的机理是什么?我们知道,我们用浏览器打开一个网页,用到的是HTTP协议,学过计算机的应该都知道这个协议,它是无状态的,什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。但是这种无状态的的好处是快速。

所以就会带来一个问题就是,我希望几个请求的页面要有关联,比如:我在www.a.com/login.php里面登陆了,我在www.a.com/index.php 也希望是登陆状态,但是,这是2个不同的页面,也就是2个不同的HTTP请求,这2个HTTP请求是无状态的,也就是无关联的,所以无法单纯的在index.php中读取到它在login.php中已经登陆了!

那咋搞呢?我不可能这2个页面我都去登陆一遍吧。或者用笨方法这2个页面都去查询数据库,如果有登陆状态,就判断是登陆的了。这种查询数据库的方案虽然可行,但是每次都要去查询数据库不是个事,会造成数据库的压力。

所以正是这种诉求,这个时候,一个新的客户端存储数据方式出现了:cookie。cookie是把少量的信息存储在用户自己的电脑上,它在一个域名下是一个全局的,只要设置它的存储路径在域名www.a.com下 ,那么当用户用浏览器访问时,php就可以从这个域名的任意页面读取cookie中的信息。所以就很好的解决了我在www.a.com/login.php页面登陆了,我也可以在www.a.com/index.php获取到这个登陆信息了。同时又不用反复去查询数据库。

虽然这种方案很不错,也很快速方便,但是由于cookie 是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了。

我擦,终于把session是怎么诞生的给圆清楚了,不容易啊!!!

好,session 诞生了,从上面的描述来讲,它就是在一次会话中解决2次HTTP的请求的关联,让它们产生联系,让2两个页面都能读取到找个这个全局的session信息。session信息存在于服务器端,所以也就很好的解决了安全问题。

session的运行机制和是怎么保存的?


既然,它也是一种服务区存储数据的方式,肯定也是存在服务器的某个地方了。确实,它存在服务器的/tmp 目录下,这一点我们接下来慢慢讲。

我们先说下它的运行机制,是怎么分配的。我们主要用PHP中session的机制,其实各种语言都差不多。

如果这个时候,我们需要用到session,那我们第一步怎么办呢?第一步是开启session:

session_start();

这是个无任何返回值的函数,既不会报错,也不会成功。它的作用是开启session,并随机生成一个唯一的32位的session_id,类似于这样:

4c83638b3b0dbf65583181c2f89168ec
session的全部机制也是基于这个session_id,它用来区分哪几次请求是一个人发出的。为什么要这样呢?因为HTTP是无状态无关联的,一个页面可能会被成百上千人访问,而且每个人的用户名是不一样的,那么服务器如何区分这次是小王访问的,那次是小名访问的呢?所以就有了找个唯一的session_id 来绑定一个用户。一个用户在一次会话上就是一个session_id,这样成千上万的人访问,服务器也能区分到底是谁在访问了。

我们做个试验,看看,是不是这样的:

我们在php.iyangyi.com 域名下的a.php 页面中,输入如下代码:

session_start(); echo "SID: ".SID."<br>"; echo "session_id(): ".session_id()."<br>"; echo "COOKIE: ".$_COOKIE["PHPSESSID"];

我们访问一下a.php页面,看能输出什么?


我们看到居然还有一个警告。我们先一个一个的看。首先 SID这个常量,我们没有给它赋值,它居然能有输出,其次 session_id()这个系统方法是输出本次生成的session_id。最后$_COOKIE['PHPSESSIID'] 没有值,这个我们接下来说。

好,我们再次刷新这个页面,我们能看到什么?


奇怪的事情发生了。SID 没有值了,$_COOKIE['PHPSESSID']中有值了。而且,2次刷新,session_id 都是一样
的:bjvlo4p38cfqkr1hr7pe924ts3,实际情况下,只要不关闭网页,怎么刷新都是一样:

既然我们看到COOKIE中有值了,我们,打开firebug开看到底是什么:


而且这个PHPSESSID的过期时间是会话,什么意思呢?就是浏览器只要不关就一直不存,浏览器一关就过期,消失了。

好,我们关掉浏览器,重新打开a.php页面,看看有没有什么变化:



你看,是不是又回到当初第一次打开时候的样子。

OK,解惑的时候到了:

每次我们访问一个页面,如果有开启session,也就是有session_start() 时,就会自动生成一个session_id 来标注是这次会话的唯一ID,同时也会自动往cookie里写入一个名字为PHPSESSID的变量,它的值正是session_id,当这次会话没结束,再次访问的时候,服务器会去读取这个PHPSESSID的cookie是否有值有没过期,如果能够读取到,则继续用这个session_id,如果没有,就会新生成一个session_id,同时生成PHPSESSID这个cookie。由于默认生成的这个PHPSESSID cookie是会话,也就是说关闭浏览器就会过期掉,所以,下次重新浏览时,会重新生成一个session_id。

好,这个是session_id,就用来标识绑定一个用户的,既然session_id生成了。那么当我们往session里面写入数据,是如何保存的,答案是保存在服务器的临时目录里,根据php.ini的配置,我机子上的这个session是存在D:\wamp\tmp 目录里的。我们先说是存在这个目录下,然后待会将如何修改。

那么它是怎么存的呢?

同样也是用到session_id。session_id是32位的,服务器会用  sess_前缀 + session_id 的形式存在这个临时目录下,比如上面这个例子:




所以,每一次生成的session_id都会生成一个这样的文件,用来保存这次会话的session信息。

我们往session里写入些数据,来看看session是怎么往这个文件里写数据的,我们同样在a.php页面继续加上写入session的语句:

$_SESSION['hello'] = 123;
$_SESSION['word'] = 456;
然后,我刷新页面,由于我并没有关闭页面,就这是说这次会话还没结束,那么肯定还会是同样的session_id :  bjvlo4p38cfqkr1hr7pe924ts3

然后,我们 用编辑器打开它的存储文件sess_bgg20mcl86drbt3j08jg5h5h17这个文件,看看里面是啥?

hello|i:123;word|i:456;
是序列化的数据,我们肉眼也能读出来。当我们往$_SESSION全局变量里写数据时,它会自动往这个文件里写入。读取session的时候,也会根据session_id 找到这个文件,然后读取需要的session变量。

这个sess文件不会随着客户端的PHPSESSID过期,也一起过期掉,它会一直存在,出息GC扫描到它过期或者使用session_destroy()函数摧毁,我们在下面讲到session·回收的时候会说到。

我们大致总结下:

HTTP请求一个页面后,如果用到开启session,会去读cookie中的PHPSESSID是否有,如果没有,则会新生成一个session_id,先存入cookie中的PHPSESSID中,再生成一个sess_前缀文件。当有写入$_SESSION的时候,就会往sess_文件里序列化写入数据。当读取的session变量的时候,先会读取cookie中的PHPSESSID,获得session_id,然后再去找这个sess_sessionid文件,来获取对应的数据。由于默认的PHPSESSID是临时的会话,在浏览器关闭后,会消失,所以,我们重新访问的时候,会新生成session_id和sess_这个文件。

好。session生成和保存将清楚了。我们再来看前面提到的几个变量:


echo "SID: ".SID."<br>";

echo "session_id(): ".session_id()."<br>";

echo "COOKIE: ".$_COOKIE["PHPSESSID"];
SID 是一个系统常量,SID包含着会话名以及会话 ID 的常量,格式为 "name=ID",或者如果会话 ID 已经在适cookie 中设定时则为空字符串,第一次显示的时候输出的是SID的值,当你刷新的时候,因为已经在cookie中存在,所以显示的是一个空字符串。

session_id() 函数用来返回当前会话的session_id,它会去读取cookie中的name,也就是PHPSESSID值。


session的相关配置

上面巴拉巴拉废话说了那么多,应该是可以理解session的一套机制了的,我接下来看看,前面零星的提到了php.ini里面有关于session相关的配置。我们打开php.ini来,搜索session相关,我主要把用到的几个给列出来:


[Session]

session.save_handler = files

session.save_path = "d:/wamp/tmp"

session.use_cookies = 1

session.name = PHPSESSID

session.auto_start = 0

session.cookie_lifetime = 0

session.serialize_handler = php

session.gc_divisor = 1000

session.gc_probability = 1

session.gc_maxlifetime = 1440
主要我们用到的,常见的大概就是这几个。我们一个一个的说。

session.save_handler = files 表示的是session的存储方式,默认的是files文件的方式保存,sess_efdsw34534efsdfsfsf3r3wrresa, 保存在 session.save_path = "d:/wamp/tmp" 里,所有这2个都是可配值得。我们上面的例子就是用的这种默认的方式。

save_handler 不仅仅只能用文件files,还可以用我们常见的memcache 和 redis 来保存。这个我们后面来说。

session.use_cookies 默认是1,表示会在浏览器里创建值为PHPSESSID的session_id,session.name = PHPSESSID 找个配置就是改这个名字的,你可以改成PHPSB, 那这样就再浏览器里生成名字为PHPSB的session_id 。`(*∩_∩*)′

session.auto_start = 0 用来是否需要自动开启session,默认是不开启的,所有我们需要在代码中用到session_start();函数开启,如果设置成1,那么session_id 也会自动就生成了。

session.cookie_lifetime = 0 这个是设置在客户端生成PHPSESSID这个cookie的过期时间,默认是0,也就是关闭浏览器就过期,下次访问,会再次生成一个session_id。所以,如果想关闭浏览器会话后,希望session信息能够保持的时间长一点,可以把这个值设置大一点,单位是秒。

gc_divisor, gc_probability, gc_maxlifetime 这3个也是配合一起使用,他们是干嘛的呢?他们是干大事情的,回收这些sess_xxxxx 的文件,它是按照这3个参数,组成的比率,来启动GC删除这些过期的sess文件。gc_maxlifetime是sess_xxx文件的过期时间。具体可以参考这个,我觉得他说我比我清楚:  session的垃圾回收机制

session的垃圾回收

我们通过上面的各种,已经清楚session的种种了,它会产生各种的sess_前缀的文件,久而久之就会形成垃圾数据,而且正常的session读取也会造成压力,所以及时的清理是蛮有用的。

1. 代码处理

php代码中有几个函数是用来清理过期的session信息的,主要是这几个:

unset($_SESSION['hello']);
session_unset();
session_destroy();
setcookie(session_name(), '', time()-42000, '/');
unset 这是是常用的销毁标量的方法,不多说,唯一要说的是删除session ,就是将这个sess_xxx的文件的hello变量给删除了,其他的变量该有的都保存着。而 session_unset() 这个不穿参数,这个是销毁sess_xxx文件中的所有变量,但是这个sess_xxx文件还是保存着。而session_destroy 则更狠角了,它是直接将这个sess_xxx文件给删掉。

一般退出操作里面,我们也会将session_name() 获得到的PHPSESSID也给过期掉,删掉,因为网页没关,不这样删除的话,刷新之后,找个值是存在的,服务器将会重新创建一个一模一样session_id的sess文件。

2. php gc 自动删除

php.ini中的几个销毁sess_xxx文件的配置,在上面说了:

session.gc_divisor = 1000
session.gc_probability = 1
session.gc_maxlifetime = 1440
简单说下,其实上面的一个超链接的博客讲的很清楚了,php触发gc删除过期的sess_x的文件的概念是这样计算的:概率= gc_probability/gc_divisor,上面的默认的参数,也就是说概念是1/1000的概念,在页面启动session_start() 函数时候,会触发gc删除过期的sess_文件。这个概率其实是蛮小的

所以,我们可以将这个概念调整大一点,比如:将gc_probability 也调成1000,那gc_probability/gc_divisor 就等于1了,也就是百分一百会触发。这样就垃圾回收概率就大的多。


用redis存储session

上面七七八八说了很多关于session的存储啊机制啊等。现在说说如果用redis 存储session。之前说的都是用文件files存储,现在想用redis,好处有哪些?
  1. 更快的读取和写入速度。redis是直接操纵内存数据的,肯定是要比文件的形式快很多。
  2. 更好的设置好过期时间。文件存储的sess_sdewfrsf文件其实被删除掉还是要考运气的和概率的,很有可能造成sess_文件没即时删除,造成存储磁盘空间过多,和读取SESSION就变慢了。
  3. 更好的分布式同步。设置redis 的主从同步,可以快速的同步session到各台web服务器,比文件存储更加快速。
总的说来,用redis来存储SESSION速度更快,性能更高。

要做的第一件事,当然就是安装redis了。具体安装和配置php与redis,就不细说了,可以参考我写的redis相关: redis安装与配置

redis 安装好了之后,接下来就是修改php.ini了。将原来的files 改成redis:

session.save_handler = redis

session.save_path = "tcp://127.0.0.1:6381"
需要用到tcp来连接redis,如果你设置reids 有密码访问的话,这样加上就可以了:tcp://127.0.0.1:6381?auth=authpwd

重启web服务器后,你就可以正常使用SESSION了。和之前使用files存储SESSION一模一样。

我们看下redis 是怎么存储session的。它是用了有别于文件存储使用sess_前缀的名字,它用PHPREDIS_SESSION: 前缀,再加上session_id 的形式,是一个string 字符串类型,带生存周期的。

PHPREDIS_SESSION:i9envsatpki9q8kic7m4k68os5



你会发现,它的值和文件存储session一模一样,都是用php序列化后存储,而且有明确的过期时间,是根据配置:session.gc_maxlifetime = 1440 来设定的,默认1440秒。当然你可以修改成其他的。

我们写入和读取每页还是一模一样,包括删除和情况,都是一模一样,没有什么变化:

session_start(); //开启session,如果读不到cookie,会重新生成一个session_id,redis里面也会新生成一个。

echo "SID: ".SID."<br>";

echo "session_id(): ".session_id()."<br>";

echo "COOKIE: ".$_COOKIE["PHPSESSID"];

$_SESSION['hello'] = 123; // 写入session 。会序列化后写入redis中
$_SESSION['word'] = 456;

var_dump($_SESSION['word']);  //读session。会从redis读到,解序列后,读出这个值。redis 1440秒过期后,将读不到。
unset($_SESSION['hello']);  // 删除 hello 的session 。会删除 redis的hello值
session_unset();  // 清空redis 中这个session_id的所有值。
session_destroy(); // 删除掉这个PHPREDIS_SESSION:i9envsatpki9q8kic7m4k68os5 key。
session同步

在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上,如果不同的服务器用的是不同的reidis服务,那么可能就会出现,一个登录用户,一会是登录状态,一会又不是登录状态。所以session这个时候就要同步了。刚好,我们选择用redis作为了存储,是可以在多台redis 服务器中同步的。

具体可以搜索 reidis主从同步或者redis 集群



参考资料:

http://zhidao.baidu.com/link?url=2_phukSt0xI6SSIVKUE37TxzivLqdCz_JCPhIUPLMB3TX_IWgoVKL2lwDn1Gh7xTykyV3ezU1YQv9s6HD3uhO_

http://blog.sina.com.cn/s/blog_5f54f0be0100xs7e.html

http://star0708.blog.163.com/blog/static/181091248201341710100381/

http://baike.baidu.com/view/25258.htm?fr=aladdin

http://www.cnblogs.com/hongfei/archive/2012/06/17/2552434.html

<think>首先,用户的问题是:“我想理解Python中Session的概念及其用途 请问Python中的Session是什么以及它的作用”。这是一个关于Python中Session的概念和用途的问题。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式,但这里可能不涉及数学表达式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 在用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 - 参考站内引用:提供了几个引用,我需要参考这些引用,但用户说“上述引用仅供参考,并不是用户真正的需求”,所以我应该基于这些引用,但专注于用户的问题。 用户提供的引用: - [^1]: 关于Python requests库中session的作用,特别是管理cookie。 - [^2]: 关于Session对象在ASP中存储用户首选项,但这里是Python上下文。 - [^3]: 关于Python爬虫中使用session来管理请求。 - [^4]: 关于微信小程序中的session_key,但这是特定于微信的。 核心是Python中的Session,特别是requests库中的session。 我的回答需要结构清晰: 1. 解释Session是什么。 2. 解释它的作用。 3. 提供示例。 4. 生成相关问题。 从引用中: - [^1] 提到session对象自动管理cookie,登录后维持cookie。 - [^3] 显示如何使用session = requests.session(),然后使用session.get()来发起请求。 所以,Session在Python中,特别是在requests库中,是用来维持状态(如cookie)在多个请求之间共享的。 回答结构: - 先定义Session。 - 解释作用:管理cookie、维持会话状态。 - 提供代码示例(如Python中使用requests.session())。 - 生成相关问题。 系统指令说“生成相关问题”,在示例中,是“§§相关问题§§”部分。 使用中文回答。 确保LaTeX正确,但这里可能不需要数学表达式。 最终回答结构: 1. 介绍Session的概念。 2. 详细说明用途。 3. 代码示例。 4. 相关问题。</think>### Python中Session的概念及其用途 在Python编程中,Session(会话)是一个核心概念,主要用于管理网络请求中的状态信息,如Cookie、身份验证令牌等。它允许在多个HTTP请求之间维持用户或客户端的上下文,从而避免每次请求都手动传递参数。Session在Web开发、爬虫和API交互中尤为重要,尤其在`requests`库(一个流行的HTTP客户端库)中被广泛应用。下面我将逐步解释Session的概念、作用,并提供示例来帮助您理解。 #### 1. **Session是什么?** Session是一个服务器端或客户端维护的状态对象,用于跟踪用户或客户端的连续操作。在Python中,Session通常通过库(如`requests`)实现: - **服务器端Session**:在Web框架(如Flask或Django)中,服务器存储用户状态(如登录信息),并通过Cookie识别客户端。 - **客户端Session**:在爬虫或API调用中,使用`requests.Session()`创建一个持久会话对象,自动处理Cookie和头信息,确保多个请求共享同一上下文。 例如,在`requests`库中,Session对象会记住请求之间的Cookie,就像浏览器一样保持会话状态[^1][^3]。 #### 2. **Session的作用** Session的主要作用是简化状态管理,提高代码效率和可靠性。具体用途包括: - **自动管理Cookie**:Session对象会自动从服务器响应中提取Cookie(如`Set-Cookie`头),并在后续请求中附加这些Cookie,无需手动传递。这在登录场景中非常有用,例如爬虫登录网站后维持会话[^1][^3]。 - 示例场景:用户登录时获取Cookie,Session确保后续请求(如访问个人页面)自动携带Cookie,避免重复登录。 - **维持会话状态**:Session可以存储共享数据(如认证令牌、用户首选项),在多个请求中复用。这减少了代码冗余和错误,例如在API调用中保持身份验证[^2][^3]。 - **优化性能**:通过重用底层TCP连接(HTTP持久连接),Session减少了网络开销,提升了请求速度,尤其在高频请求中效果显著[^1][^3]。 - **处理动态内容**:在Web应用中,Session用于跟踪用户会话(如购物车数据),在Python中可通过框架(如Flask的`session`对象)实现[^2][^4]。 引用[^1]中说明:当使用`requests.Session()`时,Cookie会被自动管理,如果手动传入Cookie,它只对单次请求生效;而Session对象则确保所有请求共享Cookie[^1]。引用[^3]进一步强调:在爬虫中,创建Session对象后,所有请求都通过它发起,从而维持状态[^3]。 #### 3. **代码示例:Python中使用Session** 以下是一个简单示例,展示如何在Python的`requests`库中使用Session来管理登录和后续请求。假设我们要模拟用户登录一个网站并访问受保护页面。 ```python import requests # 创建一个Session对象 session = requests.Session() # 初始化会话,自动管理Cookie # 登录请求:模拟用户登录,获取Cookie login_url = "https://example.com/login" login_data = {"username": "user", "password": "pass"} response = session.post(login_url, data=login_data) # 发送POST请求,Session自动处理Cookie # 检查登录是否成功 if response.status_code == 200: print("登录成功!Session已自动保存Cookie。") # 后续请求:访问个人资料页面,无需手动传入Cookie profile_url = "https://example.com/profile" profile_response = session.get(profile_url) # Session自动附加Cookie print("个人资料内容:", profile_response.text) else: print("登录失败,请检查凭证。") # 关闭Session(可选,但建议在结束时释放资源) session.close() ``` - **解释**: - `requests.Session()` 创建一个持久会话对象。 - 登录时,服务器返回的Cookie被Session自动存储。 - 后续的`session.get()`或`session.post()`调用会复用Cookie,实现无缝会话。 - 如果不使用Session,每次请求都需要手动添加Cookie,代码更繁琐且易出错[^1][^3]。 #### 4. **注意事项** - **Cookie依赖**:Session的有效性依赖于服务器支持Cookie。如果浏览器或客户端禁用Cookie,Session可能失效[^2][^4]。 - **安全性**:Session中存储敏感信息(如令牌)时,需确保使用HTTPS来防止窃听。 - **过期处理**:Session可能过期(如服务器端超时),在代码中应添加检查逻辑,例如使用`wx.checksession()`在微信小程序中验证会话状态[^4]。 - **框架差异**:在Web框架(如Flask)中,Session通常由服务器管理;而在爬虫中,`requests.Session()`是客户端实现。 总结来说,Python中的Session是一个强大的工具,用于简化HTTP请求的状态管理,核心作用是通过自动处理Cookie和共享上下文,提升代码的简洁性和效率。这在爬虫、API集成和Web开发中非常实用[^1][^2][^3]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值