php的session和并发

某天,我准备登录我们一个后台系统,前去解决一个bug,在账户密码验证码都准确输入的情况下,我登录不上,经过多次实验发现主要有两个错误信息:

我们的系统

我们的系统是基于 2.0.8 开发的,如你所见,我们在表单域加入了防止csrf攻击的域。也启用了验证码。

我首先对这两个组件进行查阅,发现他们都是将数据存于:

# phalcon/security.zep
# Security::getToken
let session = 

$this->session->set('admin_get_captcha_action', $captcha);

然后我又查阅了我们的实现,发现是将数据存储于redis的。

找啊找

什么问题导致我登录不上呢?既然是数据验证上出现问题,就从数据着手吧,我登陆我们测试环境的redis机器,执行 redis-cli ,然后走一遍登录流程,发现输出如下(意思意思):

GET sessionId  
GET sessionId  
SETEX sessionId 3600 csrf=xxxx  
SETEX sessionId 3600 captcha=abcd  

我们可以看到:

这里存在两次请求,一次是表单加载,一次是生成验证码的。 存在“并发”的情况,这两个请求应该是表单加载渲染后才请求验证码的,也就是顺序应该是get->set->get->set,看起来怎么是并发请求了。 后面那个SETEX没有csrf的内容,也就是覆盖掉前面的数据了

整个世界都不好了,不过也稍微明白是什么问题了。什么问题呢,说来话长,要从PHP的数据的存取说起。

php的数据的存取

的数据是经过编码成字符串存储在存储器【file、db、redis、等】的,在我们使用的时候,是什么时候去储存器取数据的?又是什么时候将数据写入存储器的?

这个问题的答案可能和一些朋友想的不一样,一个请求里面,PHP只会读取一次存储器,在的时候,然后也只会写入一次存储器php ===,在请求结束的时候,或调用的时候,将数据刷回存储器,关闭。

那么问题来了:

如果一个会话,同时出现两个读写请求,没有保证获取1-写入1-获取2-写入2php ===,同时没有cas版本管理机制的情况下,这些并发请求就会彼此读取不到对方的写入,最后写入的会把前面请求写入的覆盖掉。 如果请求是串行的,像登录页面的表单和验证码,也有可能前面的请求已经输出内容了,但是还没写入,后面的请求就已经发起了。锁与不锁

解决这种资源的并发一般会通过锁或版本管理来处理。但是版本管理我看不到好的方法。就聊聊锁吧。

其实锁是不大适合,有弊端的。

php的,默认是用文件存储的,在打开的时候,会对文件加独占锁,这样,其它请求就无法获取锁了php的session和并发,只能等待直到前面的锁解了。

这样保证了 读取-写入,读取-写入的顺序。

其它存储器,例如mysql,可以借助 for 进行行锁。redis可以通过一个自增键,返回1的获取到锁等来实现。

这个实现的话php的session和并发,对数据流来说很理想,但是,对于目前这种页面大量应用ajax的情况,所有请求排队处理,将大大加大页面展现的耗时php ===,甚至出现请求超时等不可用故障。

没有解决的解决不建议过多使用,其一次读取一次写入的机制所引发的问题,会造成坑的存在。 在模版渲染前,或请求输出前调用

# 立刻回写session,避免session覆盖
$eventManager = $this->view->getEventsManager;
if (!$eventManager) {  
    $eventManager = new Manager;
    $this->view->setEventsManager($eventManager);
}
$eventManager->attach("view:afterRender",function{
    session_write_close;
});
return $this->view;  

if($login) {  
    # 立刻回写session,避免session读取不到
    $eventManager = $this->dispatcher->getEventsManager;
    if (!$eventManager) {
        $eventManager = new Manager;
        $this->dispatcher->setEventsManager($eventManager);
    }
    $eventManager->attach('dispatch:afterDispatchLoop',function{
        session_write_close;
    });
    return $this->response->setHeader('Location', '/');
}

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » php的session和并发

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们