목차
回复讨论(解决方案)
백엔드 개발 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 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 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

Apple의 최신 iOS18, iPadOS18 및 macOS Sequoia 시스템 릴리스에는 사진 애플리케이션에 중요한 기능이 추가되었습니다. 이 기능은 사용자가 다양한 이유로 손실되거나 손상된 사진과 비디오를 쉽게 복구할 수 있도록 설계되었습니다. 새로운 기능에는 사진 앱의 도구 섹션에 '복구됨'이라는 앨범이 도입되었습니다. 이 앨범은 사용자가 기기에 사진 라이브러리에 포함되지 않은 사진이나 비디오를 가지고 있을 때 자동으로 나타납니다. "복구된" 앨범의 출현은 데이터베이스 손상으로 인해 손실된 사진과 비디오, 사진 라이브러리에 올바르게 저장되지 않은 카메라 응용 프로그램 또는 사진 라이브러리를 관리하는 타사 응용 프로그램에 대한 솔루션을 제공합니다. 사용자는 몇 가지 간단한 단계만 거치면 됩니다.

Hibernate는 어떻게 다형성 매핑을 구현합니까? Hibernate는 어떻게 다형성 매핑을 구현합니까? Apr 17, 2024 pm 12:09 PM

Hibernate 다형성 매핑은 상속된 클래스를 데이터베이스에 매핑할 수 있으며 다음 매핑 유형을 제공합니다. Join-subclass: 상위 클래스의 모든 열을 포함하여 하위 클래스에 대한 별도의 테이블을 생성합니다. 클래스별 테이블: 하위 클래스별 열만 포함하는 하위 클래스에 대한 별도의 테이블을 만듭니다. Union-subclass: Joined-subclass와 유사하지만 상위 클래스 테이블이 모든 하위 클래스 열을 통합합니다.

PHP에서 MySQLi를 사용하여 데이터베이스 연결을 설정하는 방법에 대한 자세한 튜토리얼 PHP에서 MySQLi를 사용하여 데이터베이스 연결을 설정하는 방법에 대한 자세한 튜토리얼 Jun 04, 2024 pm 01:42 PM

MySQLi를 사용하여 PHP에서 데이터베이스 연결을 설정하는 방법: MySQLi 확장 포함(require_once) 연결 함수 생성(functionconnect_to_db) 연결 함수 호출($conn=connect_to_db()) 쿼리 실행($result=$conn->query()) 닫기 연결( $conn->close())

HTML이 데이터베이스를 읽는 방법에 대한 심층 분석 HTML이 데이터베이스를 읽는 방법에 대한 심층 분석 Apr 09, 2024 pm 12:36 PM

HTML은 데이터베이스를 직접 읽을 수 없지만 JavaScript 및 AJAX를 통해 읽을 수 있습니다. 단계에는 데이터베이스 연결 설정, 쿼리 보내기, 응답 처리 및 페이지 업데이트가 포함됩니다. 이 기사에서는 JavaScript, AJAX 및 PHP를 사용하여 MySQL 데이터베이스에서 데이터를 읽는 실제 예제를 제공하고 쿼리 결과를 HTML 페이지에 동적으로 표시하는 방법을 보여줍니다. 이 예제에서는 XMLHttpRequest를 사용하여 데이터베이스 연결을 설정하고 쿼리를 보내고 응답을 처리함으로써 페이지 요소에 데이터를 채우고 데이터베이스를 읽는 HTML 기능을 실현합니다.

PHP에서 데이터베이스 연결 오류를 처리하는 방법 PHP에서 데이터베이스 연결 오류를 처리하는 방법 Jun 05, 2024 pm 02:16 PM

PHP에서 데이터베이스 연결 오류를 처리하려면 다음 단계를 사용할 수 있습니다. mysqli_connect_errno()를 사용하여 오류 코드를 얻습니다. 오류 메시지를 얻으려면 mysqli_connect_error()를 사용하십시오. 이러한 오류 메시지를 캡처하고 기록하면 데이터베이스 연결 문제를 쉽게 식별하고 해결할 수 있어 애플리케이션이 원활하게 실행될 수 있습니다.

PHP를 사용하여 데이터베이스에서 중국어 왜곡 문자를 처리하기 위한 팁과 사례 PHP를 사용하여 데이터베이스에서 중국어 왜곡 문자를 처리하기 위한 팁과 사례 Mar 27, 2024 pm 05:21 PM

PHP는 웹사이트 개발에 널리 사용되는 백엔드 프로그래밍 언어로, 강력한 데이터베이스 운영 기능을 갖추고 있으며 MySQL과 같은 데이터베이스와 상호 작용하는 데 자주 사용됩니다. 그러나 한자 인코딩의 복잡성으로 인해 데이터베이스에서 잘못된 한자를 처리할 때 문제가 자주 발생합니다. 이 기사에서는 잘못된 문자의 일반적인 원인, 솔루션 및 특정 코드 예제를 포함하여 데이터베이스에서 중국어 잘못된 문자를 처리하기 위한 PHP의 기술과 사례를 소개합니다. 문자가 왜곡되는 일반적인 이유는 잘못된 데이터베이스 문자 집합 설정 때문입니다. 데이터베이스를 생성할 때 utf8 또는 u와 같은 올바른 문자 집합을 선택해야 합니다.

Golang을 사용하여 원격 데이터베이스에 연결하는 방법은 무엇입니까? Golang을 사용하여 원격 데이터베이스에 연결하는 방법은 무엇입니까? Jun 01, 2024 pm 08:31 PM

Go 표준 라이브러리 데이터베이스/sql 패키지를 통해 MySQL, PostgreSQL 또는 SQLite와 같은 원격 데이터베이스에 연결할 수 있습니다. 데이터베이스 연결 정보가 포함된 연결 문자열을 생성합니다. sql.Open() 함수를 사용하여 데이터베이스 연결을 엽니다. SQL 쿼리 및 삽입 작업과 같은 데이터베이스 작업을 수행합니다. 리소스를 해제하기 위해 defer를 사용하여 데이터베이스 연결을 닫습니다.

See all articles