目錄
回复讨论(解决方案)
首頁 後端開發 php教程 数据库连接灵异事件探讨,资深的高手请进,紧急!

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

Jun 23, 2016 pm 01:55 PM
事件 資料庫 高手

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

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Go語言如何實作資料庫的增刪改查操作? Go語言如何實作資料庫的增刪改查操作? Mar 27, 2024 pm 09:39 PM

Go語言是一種高效、簡潔且易於學習的程式語言,因其在並發程式設計和網路程式設計方面的優勢而備受開發者青睞。在實際開發中,資料庫操作是不可或缺的一部分,本文將介紹如何使用Go語言實作資料庫的增刪改查操作。在Go語言中,我們通常會使用第三方函式庫來操作資料庫,例如常用的sql套件、gorm等。這裡以sql包為例介紹如何實作資料庫的增刪改查操作。假設我們使用的是MySQL資料庫。

iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 Jul 18, 2024 am 05:48 AM

蘋果公司最新發布的iOS18、iPadOS18以及macOSSequoia系統為Photos應用程式增添了一項重要功能,旨在幫助用戶輕鬆恢復因各種原因遺失或損壞的照片和影片。這項新功能在Photos應用的"工具"部分引入了一個名為"已恢復"的相冊,當用戶設備中存在未納入其照片庫的圖片或影片時,該相冊將自動顯示。 "已恢復"相簿的出現為因資料庫損壞、相機應用未正確保存至照片庫或第三方應用管理照片庫時照片和視頻丟失提供了解決方案。使用者只需簡單幾步

Hibernate 如何實作多型映射? Hibernate 如何實作多型映射? Apr 17, 2024 pm 12:09 PM

Hibernate多態映射可映射繼承類別到資料庫,提供以下映射類型:joined-subclass:為子類別建立單獨表,包含父類別所有欄位。 table-per-class:為子類別建立單獨資料表,僅包含子類別特有列。 union-subclass:類似joined-subclass,但父類別表聯合所有子類別列。

在PHP中使用MySQLi建立資料庫連線的詳盡教學 在PHP中使用MySQLi建立資料庫連線的詳盡教學 Jun 04, 2024 pm 01:42 PM

如何在PHP中使用MySQLi建立資料庫連線:包含MySQLi擴充(require_once)建立連線函數(functionconnect_to_db)呼叫連線函數($conn=connect_to_db())執行查詢($result=$conn->query())關閉連線( $conn->close())

如何在PHP中處理資料庫連線錯誤 如何在PHP中處理資料庫連線錯誤 Jun 05, 2024 pm 02:16 PM

PHP處理資料庫連線報錯,可以使用下列步驟:使用mysqli_connect_errno()取得錯誤代碼。使用mysqli_connect_error()取得錯誤訊息。透過擷取並記錄這些錯誤訊息,可以輕鬆識別並解決資料庫連接問題,確保應用程式的順暢運作。

深入解析HTML如何讀取資料庫 深入解析HTML如何讀取資料庫 Apr 09, 2024 pm 12:36 PM

HTML無法直接讀取資料庫,但可以透過JavaScript和AJAX實作。其步驟包括建立資料庫連線、發送查詢、處理回應和更新頁面。本文提供了利用JavaScript、AJAX和PHP來從MySQL資料庫讀取資料的實戰範例,展示如何在HTML頁面中動態顯示查詢結果。此範例使用XMLHttpRequest建立資料庫連接,發送查詢並處理回應,從而將資料填入頁面元素中,實現了HTML讀取資料庫的功能。

如何用 Golang 連接遠端資料庫? 如何用 Golang 連接遠端資料庫? Jun 01, 2024 pm 08:31 PM

透過Go標準庫database/sql包,可以連接到MySQL、PostgreSQL或SQLite等遠端資料庫:建立包含資料庫連接資訊的連接字串。使用sql.Open()函數開啟資料庫連線。執行SQL查詢和插入操作等資料庫操作。使用defer關閉資料庫連線以釋放資源。

如何在 Golang 中使用資料庫回呼函數? 如何在 Golang 中使用資料庫回呼函數? Jun 03, 2024 pm 02:20 PM

在Golang中使用資料庫回呼函數可以實現:在指定資料庫操作完成後執行自訂程式碼。透過單獨的函數新增自訂行為,無需編寫額外程式碼。回調函數可用於插入、更新、刪除和查詢操作。必須使用sql.Exec、sql.QueryRow或sql.Query函數才能使用回呼函數。

See all articles