1、背景php
最近在作一个面向三端【H五、IOS、安卓】的短信验证码登陆接口。发送短信验证码时,服务端经过 session 保存验证码的值。登陆时,从 session 获取验证码和用户输入的验证码java
相比较。在这过程当中,H5 端 session 的设置、读取都没有问题。可是 IOS 、安卓端能够正常设置 session 值,可是在登陆时,读取的 session 值为空,致使业务逻辑异常中断。数据库
2、缘由编程
一、PC 端多个请求,会使用同一个 PHPSESSID ;数组
二、移动端【IOS 安卓】多个请求,会使用不一样的PHPSESSID。好比发送验证码时的 PHPSESSID = t5arr13hh352gaekn255jvrk36,登陆时的 PHPSESSID = 44jh1hgcc07v0bi07i652vbnv1;浏览器
由于 PHPSESSID 的不一致,致使了移动端【IOS 安卓】不能正常读取 session 值。服务器
3、参考解决方案cookie
移动端人为设置 PHPSESSID ,并保持有业务管理的接口中的 PHPSESSID 一致便可。session
4、Session 原理
数据结构
提到session,你们确定会联想到登陆,登陆成功后记录登陆状态,同时标记当前登陆用户是谁。功能大致上就是这个样子,可是今天要讲的不是功能,而是实现。经过探讨session的实现方式来发掘一些可能你以前不知道的有趣的事情。
为了记录session,在客户端和服务器端都要保存数据,客户端记录一个标记,服务器端不但存储了这个标记同时还存储了这个标记映射的数据。好吧,仍是说点白话吧,在客户端记录的实际上是一个sessionid,在服务器端记录的是一个key-value形式的数据结构,这里的key确定是指sessionid了,value就表明session的详细内容。用户在作http请求的时候,老是会把sessionid传递给服务器,而后服务器根据这个sessionid来查询session的内容(也就是上面说到的value)。
如今咱们重点关注一下sessionid,他是今天问题的关键所在。sessionid在客户端(http的客户端通常就是指浏览器了)是存储在cookie中,固然也有例外(书本上确定会提到也有保存在url中的)。
咱们经过一个例子来阐述一下这个sessionid在session处理时的做用。首先假定这么一个场景,咱们有一个cms(content management system,内容管理系统),这个应用有一个后台,用户必须登陆才能进入后台进行文章发表等操做。首先是登陆流程,用户在浏览器输入用户名、密码,点击登陆,浏览器会将用户名密码提交到服务器程序进行处理;服务器验证用户名、密码正确后,会返回登陆成功信息,而且会修改服务器端的session内容,好比咱们将用户ID写入session中,为了方便存储这些session的内容会被序列化成字符串或者二进制保存在文件或者数据库中,这时候大多数状况下服务器在对当前的http请求进行响应时,会返回一个新的sessionid要求浏览器写入本地cookie中,对应的返回的http响应头部信息应该会是是这个样子的:set-cookie:PHPSESSID=xxxxxxx,浏览器解析到这个头以后就会在当前生成一个cookie关联当前的域名。
接着用户登陆后台进行发表文章操做,登陆用户填写文章的标题、内容,而后点击发送。这时候浏览器会生成一条到服务器的http请求,注意这个请求的头部会将存储sessionid的cookie内容发送过去,也就是说请求的http头部信息中应该会有这么一段数据:cookie:PHPSESSID=xxxxxxx;other_cookie_name=yyyyyy;服务器接收到这个http请求以后,解析到cookie存在,且cookie中存在PHPSESSID这个cookie名字,而后就将PHPSESSID的值(也就是sessionid的值)取出来,根据这个PHPSESSID查询服务器上有没有对应的session内容,若是有则将其对应的值取出来进行反序列序列化(也就是将其转成编程语言中的一个数据结果,好比在php中会获得一个$_SESSION数组,在j2ee中会获得类型为javax.servlet.http.HttpSession),方便在程序中进行读取,最终服务器认定session中储存的值存在,而且从反序列化获得的对象中读取到了用户ID属性,而后就往cms数据库的文章表中插入了一条数据,最终返回http响应,告诉浏览器操做成功了。