MYSQL老密码与php版本扩展关系
mysql的用户密码保存在数据库中是加密的。不可逆的。当需要创建一个新的帐号,如果是使用insert插入一条记录,
mysql提供了一个函数PASSWORD(),对明文进行加密。所以有如下sql:
insert into mysql.user values('帐号名',PASSWORD('设置的帐号密码'));
但是,mysql4.1版本之前有些不同。当你使用php扩展库连接的时候。
old_password()就是按照之前的版本设置设置mysql密码。
可否这样理解:
mysql4.1版本之前的密码加密方式与之后的版本加密方式不同。因而就需要使用这个函数?
想想,新版本的为什么改进了原来的16个字符加密,而使用41个字符串的形式加密密码明文?
可以认为是出于安全考虑(手册中介绍为什么提供old_password(),隐约提到安全考虑)。字符越多越难破解?减少密码被截获的风险
mysql4.1版本之前与>=4.1版本,区别就是password()函数被重写了。生成的加密串长度一个是16位,一个为41位。
总结:mysql提供一个old_password函数与my.conf中old_passwords配置选项,就是为了使密码兼容4.1之前版本的加密方式。
比如:假如数据从4.0迁移到5.1版本服务器上。那么user表中密码方式不一样。如果开启这个选项,则还是按照4.0的版本进行加密。
疑问:但是实际用处多大?
网上提到的解决办法
SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');
含义为:对于需要使用mysql4.1版之前的客户端的用户,将密码恢复为4.1版之前的风格。
因为old_password()函数生成的密码的加密方式是,按照4.1之前的版本生成。所以上面就是按照<=4.0的版本的加密方式保存密码。
SET PASSWORD FOR '帐号' = 密码加密后的值;#为某某帐号设置密码为xxx
不过,我遇到的实际情况不一样的,只是也报这种错误。
环境:mysql 是5.0
PHP使用5.3的话才报出这种错误。
如果php切换到5.2则问题消失。
分析:说明。如果用5.3版本中的mysql扩展去连接5.0的mysql服务器,出现了问题。是扩展的问题。
php中的mysql扩展实质上就是一个mysql客户端。是客户端不兼容的问题??
已经知道是mysql版本原因。生成密码的时候4.1版本是生成16个字符。后续版本是生成总计41(生成40个后在前面统一加上一个*)个字符了。
既然如此,我的情况mysql的版本是5.0版本,所以生成的应该 41个字符。那么,即使我使用的是php.5.3版本的扩展,也不会有影响才对?
对于这个函数的解释,手册翻译没有翻译好,词不达意,摘录台湾解释版本:
OLD_PASSWORD(str)
str 傳入的明文密碼
回傳MySQL 4.1版之前的PASSWORD結果。
OLD_PASSWORD()會被增加到MySQL函數是為了改善安全性造成的問題。OLD_PASSWORD()回傳MySQL 4.1版之前的PASSWORD結果,同時允許你使用任何4.1之前的連接程式使用原本的密碼連線到你的MySQL伺服器,避免他們被中斷服務。
疑问:调用OLD_PASSWORD函数会对mysql服务器密码机制造成什么影响吗?或者会改变原来的密码加密方式。导致其他客户端连接出现问题?
不会。old_password(),只是对当前密码明文使用何种方式加密(加密16个字符)。其实在4.1版本之前,密码都是以16个字符加密保存的。
而my.conf中的配置选项"old_passwords = 1;"可以配置使用旧的(表示4.1版本之前)密码加密方式生成密码保存到user表。影响的地方在于:
当使用grant(该命令会涉及到创建密码)分配帐号。
或者使用"set password for '帐号' = password('密码明文');"的时候。因为受到my.conf配置的影响,password()实际上是使用旧的方式加密,即加密成16个字符。
疑问:我使用php5.2版本里面的mysql扩展连接"旧的加密方式"的mysql服务器。为什么没有报错,能够连接?
与客户端有关?
确定的事情为:客户端尝试连接mysql服务器的时候。mysql服务器会将从客户端接收到密码明文,调用password(),生成加密hash值(通俗点就是加密后的字符),然后与mysql.user表中的Password字段对比。
所以,为什么删掉my.conf中的"old_passwords=1",有些人就连接出错。原因为:之前该配置是打开的。所以生成的密码都是16个字符保存在user表中。现在删掉后,客户端连接,调用的password()函数是生成41个字符,所以就对比不上了。
mysql为什么不是提示密码错误?
mysql对比user表发现里面保存的是16个字符,与生成的41个字符有长度上的区别,所以告诉你是版本上的原因。
疑问:既然mysql能够明确知道16个字符与41个字符的区别。说明已经知道是什么原因了。为什么没有自动调用旧的加密方式对客户端的明文密码加密?可能是安全考虑。
上面一部分理解错误的:
客户端连接服务器的时候,是客户端调用password()函数生成密码hash值。而非服务器。所以很容易明白为什么与客户端版本有关系了。
客户端版本是5.1,可以连接到4.1之前的服务器。
但是4.1之前的版本的客户端却无法连接到5.1版本的服务器。
基于上述情况,所以很容易确定,"更高版本的mysql客户端是能够向下兼容连接mysql4.1之前的服务器的"。
实际上变成了,mysql服务器与mysql客户端之间的版本兼容问题了。
疑问:既然客户端是向下兼容的,为什么5.3php的客户端无法连接就加密方式的mysql呢?
要理清楚,客户端之间的关系是什么?
发现原因是其他的。因为php5.3版本中的mysql扩展完全不同:集成在php源码中发布的,因而属于php一部分
php5.3版本用的扩展库是mysqlnd 5.0.7-dev - 091210 - $Revision: 304625 $ 。
而5.2版本用的扩展库为5.0
关于其说明:
PHP5.3 和 PHP6 中,均采用了 mysqlnd 做为 mysql 数据库的默认驱动.
mysqlnd 是在 PHP 源码树中集成, 与原先的 libmysql 不同, mysqlnd 与内核联系更紧密.
看来上面说明,已经确定原因了。php中的mysql扩展确实能够向下兼容,能正常访问mysql4.1之前的服务器(否则php5.2的5.0mysql扩展就无法访问基于old_password加密方式的mysql服务器了)。
但是,由于php5.3中嵌入的扩展完全是另一种架构了。所以无法连接。
#############################
php5.3版本开始,使用的mysql扩展是集成在php源码中发布。
省。
1.版权考虑:就的mysql扩展库是由mysqlab公司(现在是甲骨文)所写,那么就是在该公司的协议下发布(版权)。那么有些功能就会被禁用掉。写入php源码一部分,会解决过去的版本发布的问题。去安装,相当于安装了php,就安装了mysql扩展
2.内存使用效率提高。以前是复制数据两份,现在只需一份。
新版本由于扩展集成在php源码中,是php一部分。(mysql_fetch_assoc())是复制一份数据到php中了。以前就是复制一份到扩展中,同时复制一份到php中。所以是两份。
####################################
测试代码:
#SELECT PASSWORD('123'),LENGTH(PASSWORD('123'));
#SET SESSION old_passwords=1;
SELECT PASSWORD('123'),LENGTH(PASSWORD('123'));
SHOW GLOBAL VARIABLES LIKE '%old_passwords%'##查看my.conf中配置项设置值。注意:不加gloabl,则默认是取得session变量的值(当前连接生效的值)
实际处理总结:把密码改成16位,还是32位形式保存到user表中去。有多个客户端在连接mysql。那么就意味着有多个扩展。那么只要保证php中的扩展能够正常连接即可。
转自:http://www.cnblogs.com/wangtao_20/archive/2012/04/04/2432221.html