面试常问的Session相关问题.

面试常问的Session相关问题.

Session和Cookie的关系?

Cookie是什么?

Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息。
如何识别特定的客户呢?cookie就可以做到。每次HTTP请求时,客户端都会发送相应的Cookie信息到服务端。
它的过期时间可以任意设置,如果你不主动清除它,在很长一段时间里面都可以保留着,即便这之间你把电脑关机了。

Session是什么?

Session是在无状态的HTTP协议下,服务端记录用户状态时用于标识具体用户的机制。
它是在服务端保存的用来跟踪用户的状态的数据结构,可以保存在文件、数据库或者集群中。
在浏览器关闭后这次的Session就消失了,下次打开就不再拥有这个Session。
其实并不是Session消失了,而是Session ID变了,服务器端可能还是存着你上次的Session ID及其Session 信息,
只是他们是无主状态,也许一段时间后会被删除。

关系?

  1. Cookie 在客户端(浏览器),Session 在服务器端。

  2. Cookie的安全性一般,他人可通过分析存放在本地的Cookie并进行Cookie欺骗。在安全性第一的前提下,选择Session更优。
    重要交互信息比如权限等就要放在Session中,一般的信息记录放Cookie就好了。

3.单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie

  1. Session 可以放在 文件、数据库或内存中,比如在使用Node时将Session保存在redis中。由于一定时间内它是保存在服务器上的,
    当访问增多时,会较大地占用服务器的性能。考虑到减轻服务器性能方面,应当适时使用Cookie。

  2. Session 的运行依赖Session ID,而 Session ID 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie,Session 也会失效
    (但是可以通过其它方式实现,比如在 url 中传递 Session ID)

  3. 用户验证这种场合一般会用 Session。因此,维持一个会话的核心就是客户端的唯一标识,即Session ID

禁用了Cookie还可以继续使用Session吗? 如何使用?

如果客户端的浏览器禁用了 Cookie 怎么办?建议使用URL重写技术进行会话跟踪,
即每次HTTP交互,URL后面都被附加上诸如 sid=xxxxx 的参数,以便服务端依此识别用户。

面试的时候经常被问到Cookie禁用了,Session还能用吗?

默认SESSION配置

默认的PHP配置中,SessionID是需要存储在Cookie中的,默认Cookie名为:

  • PHPSESSIONID

以下以PHP为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 你第一次访问网站时,

2. 服务端脚本中开启了Session session_start();,

3. 服务器会生成一个不重复的SESSIONID 的文件'session_id();',比如在'/var/lib/php/session'目录

4. 并将返回(Response)如下的HTTP头 'Set-Cookie:PHPSESSIONID=xxxxxxx'

5. 客户端接收到'Set-Cookie'的头,将'PHPSESSIONID'写入cookie

6. 当你第二次访问页面时,所有Cookie会附带的请求头(Request)发送给服务器端

7. 服务器识别'PHPSESSIONID'这个cookie,然后去session目录查找对应session文件,

8. 找到这个session文件后,检查是否过期,如果没有过期,去读取Session文件中的配置;如果已经过期,清空其中的配置

如果客户端禁用了Cookie,那PHPSESSIONID都无法写入客户端,Session还能用?

答案显而易见:不能

并且服务端因为没有得到PHPSESSIONID的cookie,会不停的生成session_id文件

取巧传递session_id

但是这难不倒服务端程序,聪明的程序员想到,如果一个Cookie都没接收到,基本上可以预判客户端禁用了Cookie,
那将session_id附带在每个网址后面(包括POST),比如:

1
2
GET http://www.xx.com/index.php?session_id=xxxxx
POST http://www.xx.com/post.php?session_id=xxxxx

然后在每个页面的开头使用session_id($_GET['session_id']),来强制指定当前session_id

这样,答案就变成了:

但是这样做的方式是不可取的。为什么?因为有风险!

聪明的你肯定想到,那将这个网站发送给别人,那么他将会以你的身份登录并做所有的事情(目前很多订阅公众号就将openid附带在网址后面,这是同样的漏洞)。

其实不仅仅如此,cookie也可以被盗用,比如XSS注入,通过XSS漏洞获取大量的Cookie,也就是控制了大量的用户,腾讯有专门的XSS漏洞扫描机制,因为大量的QQ盗用,发广告就是因为XSS漏洞

所以Laravel等框架中,内部实现了Session的所有逻辑,并将PHPSESSIONID设置为httponly并加密,这样,前端JS就无法读取和修改这些敏感信息,降低了被盗用的风险。

如何实现Session共享?

为什么要session共享?

现在稍微大一点的网站基本上都有好几个子域名,比如www.caoxl.com, search.caoxl.com, member.caoxl.com,这些网站如果需要共用用户登录信息,那么就需要做到session共享,当然前提是有相同的主域

要解决session共享,就必须解决两个问题:

    1. 多台服务器用同一个session_id

这个比较容易解决,只要在php中设置存session_id的cookie域名为网站主域就可以了
打开PHP.ini, 设置session.cookie_domain = .caoxl.com,
当然也可以在php代码当中设置ini_set("session.cookie_domain","caoxl.com");

    1. 多台服务器用同一个session_id访问到相同的session内容

要实现这点,就必须把session内容存储到让所有服务器都能访问到的地方,php的session内容是默认存储到本服务器的文件中的,一般的解决方案是存入数据库,memcache或者redis这种缓存服务器,
当然用默认的文件存储方式也可以,用NFS统一存储。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2023 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :