Heim  >  Artikel  >  Backend-Entwicklung  >  数据库连接灵异事件探讨,资深的高手请进,紧急!

数据库连接灵异事件探讨,资深的高手请进,紧急!

WBOY
WBOYOriginal
2016-06-23 13:55:401041Durchsuche

做了一个SAAS模式的ERP系统, 目前做法是为每个企业建立一个数据库,但是公用一套PHP脚本。 比如我的SAAS客户有50家企业,等于我在MYSQL里建了50个DB, 数据结构都一样的。 然后PHP脚本就一套,这样升级比较方便, 修改一个地方,等于50套系统都升级了。
每个企业登录第一页的时候,我都给他们存了一个SESSION['db'],在php连接数据库的脚本里,连接DB的名称=SESSION['db'], 这样这个企业就固定在那个数据库里增删改查。 

现在灵异的事件,就是偶尔会发生串号现象。  比如A企业, 他第一页登录的时候,设置SESSION['DB'] = 'A',然后再login的时候,到名称为A的数据库里check 用户名密码,再接下去增删改查都是A数据库里的表格。  可是偏偏偶尔出现,A企业登录以后,刷新一下,突然变成B企业的数据, 再刷新一下C企业的数据出现。 我就纳闷, connection里,DB已经固定死为A了,为什么会串号到其他的数据库的数据里去呢?  

我自己第一次分析, 因为脚本都是一样的,意味URL都是一样的。 理论上,SESSION['db']都不一样,页面每次打开都是自己连接自己的,应该也没啥问题,既然出现串号,我就在怀疑缓存之类造成的。 后来网络上一查,好像360浏览器被人举报上传用户隐私,链COOKIE也上传,当时在想是不是360浏览器这个动作造成的。 

第一次应对措施, 我利用域名泛解析, 把每个企业的网址都修改为不一样了,也就是A企业的网址是A.xxx.com B企业是b.xxx.com ,但是整体框架还是一样的,PHP脚本也是同一套。 这样的话360就算把COOKIE上传到他服务器缓存中,网址不一样了,总不会串号了吧?  可事实证明我又错了。 下午又有客户来电话说怎么在他的系统里看到别的公司的数据。 我彻底疯了。

我自己第二次分析,我怀疑是不是mysql_pconnect() 连接造成的? 我在想A企业建立了一个数据库持久连接。 B企业登录也是mysql_pconnect() , APACHE会不会直接拿A企业建立的连接来给B企业用?  所以我晚上立马把pconnect修改为connect。 但还是很担心,感觉问题不是那么简单,这个数据串号对于一个商业软件,后果实在太严重了。 我花了太多心血在里面,说不定就功亏一篑。

再次恳求高手帮我分析一下,怎么会出现这种奇特的现象? 我多次怀疑缓存原因,可就算显示的是缓存页面,理应无法相互修改, 所以感觉问题还是出现在数据库连接上?

我的QQ是13676987,杭州,  期待与高手交流!


回复讨论(解决方案)

1.SESSION['db'] 是$_SESSION['db']吗?
2.为什么要把dbname写在session?
为什么不没个site用一个config文件记录不同的信息,例如 每个site都有一个config.php,
define('DBNAME', 'db1');
3.你的session是保存在db吗?

50个企业共用一套PHP脚本,意味着 config.php只有一个, 50个企业一起用。 所以无法单独设置。 不过你到是给我一个灵感,我可以弄config1.php  config2.php config3 ...... 这样, 搞50个也未尝不可呢?

也是一个蛮好的解决方案,虽然有点傻。呵呵

如果这样,那么50个virtual host应该是不同了吧。
使用apache 的 Env module,使用方法见我之前写的文章: http://blog.csdn.net/fdipzone/article/details/9388959

在virtual host中,加入

<IfModule mod_env.c>  SetEnv DBNAME DB1</IfModule> 

不同的virtual host 的值设置不同。

然后在config 原来设置dbname的地方。
例如:$dbname = 'DB1'; 改为 $dbname = $_SERVER['DBNAME'];

tips:使用Env保存的数据只能在web读取,在php cli模式下是不能读取的,请根据具体需求使用。

数据库长连接是会复用到数据库服务器的连接,但不会复用到数据库的连接

说怎么在他的系统里看到别的公司的数据入手:
从“第一次应对措施, 我利用域名泛解析”可知,你的用户身份验证是独立的。目前SSO很流行,不排除你也在使用
既然若干个公司可以使用同一套软件而无需修改(包括界面),可见这些公司从事的是同一行业。因此不能排除A公司的人知道B公司人的登录口令
用多选项卡的浏览器,在A选项卡上登录A公司后,在B选项卡上登录B公司。回到A选项卡中就可看到B公司的数据了
因为多选项卡共享一个cookie,而A设置的 sessionid 被B修改了
其实无条件信任传入的数据,这就是CSRF攻击得以实现的基础

当采用二级域名方式时,因为域名不同所以cookie也不会共用。但是如果依然是单点登录的话,由于信任域的关系,情况不会有任何改变

目前太多的人不相信数据库的能力,喜欢弄个数据缓存之类的东西(怕数据库累死了,怜悯精神可嘉)
数据缓存多以查询名区分,而在你的系统中区分数据隶属关系的是库名,弄混淆了也是很正常的


数据库长连接是会复用到数据库服务器的连接,但不会复用到数据库的连接

说怎么在他的系统里看到别的公司的数据入手:
从“第一次应对措施, 我利用域名泛解析”可知,你的用户身份验证是独立的。目前SSO很流行,不排除你也在使用
既然若干个公司可以使用同一套软件而无需修改(包括界面),可见这些公司从事的是同一行业。因此不能排除A公司的人知道B公司人的登录口令
用多选项卡的浏览器,在A选项卡上登录A公司后,在B选项卡上登录B公司。回到A选项卡中就可看到B公司的数据了
因为多选项卡共享一个cookie,而A设置的 sessionid 被B修改了
其实无条件信任传入的数据,这就是CSRF攻击得以实现的基础

当采用二级域名方式时,因为域名不同所以cookie也不会共用。但是如果依然是单点登录的话,由于信任域的关系,情况不会有任何改变

目前太多的人不相信数据库的能力,喜欢弄个数据缓存之类的东西(怕数据库累死了,怜悯精神可嘉)
数据缓存多以查询名区分,而在你的系统中区分数据隶属关系的是库名,弄混淆了也是很正常的



意思是问题出在缓存中? 如果每次都连数据库获取,则没有此问题吗?

如果没有使用缓存,则去掉了问题可能存在的一个方面
如果不仅仅信任 $_SESSION['db'],而是再有至少一种 判定用户来源的手段的话,则又可以去掉问题可能存在的一个方面
当你把已知的可能出问题的方面都排除了,问题还没解决
那就是还有未知的潜在问题存在,这才是需要讨论的问题

楼主也是这个意思,他希望你把你知道的可能出现问题的方面罗列出来,以便于他排查
至于如何解决,那是后话了。问题没有找到,任何解决方案都是徒劳的

意思是问题出在缓存中? 如果每次都连数据库获取,则没有此问题吗?

数据库长连接是会复用到数据库服务器的连接,但不会复用到数据库的连接



我还是比较怀疑是长连接的问题。 您说的没错, “长连接是会复用到数据库服务器的连接”, 前提是此连接的用户名和密码一样,而我恰恰是所有企业连接到服务器的用户名都是一样的,只是在到数据库的链接的时候,用SESSION[''DB']去区分。  所以请教下这种情况,有没有存在一定的概率,把数据库的链接也给复用了?尤其是SESSION['DB']因为某种不确定原因被清空了的时候?

既然若干个公司可以使用同一套软件而无需修改(包括界面),可见这些公司从事的是同一行业。因此不能排除A公司的人知道B公司人的登录口令。



这个100%可以排除。 

如果是数据库缓存导致的,就和我第一帖分析的一样,不应该连其他企业的数据也可以修改。 因为缓存仅仅是读取,针对SELECT, 不可能连UPDATE DELETE都能生效的。 对吧?

感谢各位的热心帮助。 我再努力排查排查。 感觉学到不少

tips:使用Env保存的数据只能在web读取,在php cli模式下是不能读取的,请根据具体需求使用。


我没有用50个 VIRTUAL HOST, 就一个, 只是利用域名的泛解析。 把所有二级域名都指向一个virtual host。 

有没有存在一定的概率,把数据库的链接也给复用了?
绝无存在的可能

尤其是SESSION['DB']因为某种不确定原因被清空了的时候?
如果 SESSION['DB'] 被清空,那么就相当于执行 mysql_select_db('') 这是要出错的 (No database selected)

我说的缓存是指项目的 cache 功能
一般用于缓存查询结果,频繁访问时不去读数据库

如果用二级域名,则应将二级域名与数据库名绑定

mark,新人路过学习一下
如果是我做这个东西,会把客户单独建表,然后每个数据表和索引都加上一个客户ID字段,弄一个简易的总后台添加客户,这样方便管理~
前台的Model层传入where xxx 筛选变量时,统一添加上客户ID=xxx~不过不确定这样做法的弊端


tips:使用Env保存的数据只能在web读取,在php cli模式下是不能读取的,请根据具体需求使用。


我没有用50个 VIRTUAL HOST, 就一个, 只是利用域名的泛解析。 把所有二级域名都指向一个virtual host。 

?怪,不?提供的信息不算太多。比??分析,老大已?分析得比?全面了。

你是根?域名,即$_SERVER['HOST'] 判?使用什?????接??

能否提供那部分的代??考呢?

目前我的做法是每一家公司使用一??立的域名,程式根?不同的域名??取各自不同的配置?.
a公司用http://a.xx.com
b公司用http://b.xx.com

??不跨域,目前多?企?之??有出?串??的??,一直表?的比??定,你可以借?看看.

目前我的做法是每一家公司使用一??立的域名,程式根?不同的域名??取各自不同的配置?.
a公司用http://a.xx.com
b公司用http://b.xx.com

??不跨域,目前多?企?之??有出?串??的??,一直表?的比??定,你可以借?看看.



这个做法蛮好的。 要是早点知道就用你的方法了。 呵呵

xuzuning版主很强大。 
我先结贴了。 目前做法就是在几个地方设置了异常的判断,如果再次出现再来请教!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn