事情是这样。前段时间跟同学在校内架起了一个PT网站,代码是从sourceforge.org上下的tbdev。
因为对mysql不熟,数据库默认字符集设为了utf-8
前台页面的charset设成了GBK
正常运行了一段时间。但现在网站要进行升级。字符集问题出现了。
phpmyadmin查看文本字段里面的信息是乱码,不能正常查询。
于是查资料,把gbk编码成功转成了UTF-8编码。前台页面也设成了UTF-8。虽然中文显示正常了,但最关键的用户注册信息有问题。
我要保留原网站的用户注册信息,关键是密码。站点采用MD5方式加密。数据库中有个secret字段 是 varchar类型。 字符集为 UTF-8 
保存的是以GBK方式编码的 0-255的随机ASCII字符还有个passhash字段 是 varchar类型。字符集为UTF-8
保存的是进行如下计算的字符串
md5($row["secret"] . $password . $row["secret"])登陆时作如下判断 
if ($row["passhash"] != md5($row["secret"] . $password . $row["secret"]))
bark();升级时为解决乱码问题。在连接数据库之前执行了
mysql_query("SET NAMES utf8");但是如果Connection指定字符集为UTF-8后,MD5计算出的passhash就变了。
如果执行mysql_query("SET NAMES latin1");
则MD5计算出的结果正常。我试过将secret字段中的文本转换编码,但没有成功。MD5计算出的passhash还是不一样。我想到一个方法就是把secret字段转化成 blob类型。我测试过,二进制类型的数据传输时不受连接字符集编码的影响。
但是我现在不知道该如何把字符串转化为二进制流存入 blob类型的字段中。或者大虾位有没有别的解决方法?即保证字符集统一,又能保证用户正确登陆?

解决方案 »

  1.   

    把secret导出转换成UTF-8再存回去.
      

  2.   

    对 conqweal :我试过直接存,读出的结果经MD5计算还是不对。
    我在数据库中建了一个结构相同的users_bak表
    仅仅是把secret字段改成了blob类型。转化代码如下:<?
    require_once("include/bittorrent.php");dbconn(); //数据库连接函数;mysql_query("SET NAMES latin1");$res = mysql_query("SELECT id, passhash, secret, enabled FROM users WHERE username = 'testusername'");
    $row = mysql_fetch_assoc($res);$secr=$row["secret"];
    $password="test";print "secret:".$row["secret"]."/passhash:".$row["passhash"];
    print "<br>md5:".md5($row["secret"] . $password . $row["secret"]);mysql_query("SET NAMES utf8");
    mysql_query("UPDATE users_bak SET secret='".$row["secret"]."' WHERE username='testusername'");print "<br>Convert finish.";
    ?>
    结果读出的值经md5计算,还是不一样。
      

  3.   

    对 runffer_yang :   我试着转化过。我是这么转化的mysqldump -u root -p --default-character-set=latin1 --set-charset=false tbdev users > users.sql然后用 UltraEdit 将sql文件中的 utf8 换成 gbk 
    再导入到 字符集为 GBK 的 tbdev_gbk 数据库中mysql -u root -p --default-character-set=gbk tbdev_gbk < user.sql其它字段由乱码转化成了正常的中文。
    但secret字段中的值变了。
    读出来的字符串经MD5加密后,结果也变了。
    不能正常登陆
      

  4.   

    将数据库编码格式改为GBK吧。这样会好一些。
      

  5.   

    其实如果不保留原有注册信息,把编码统一为UTF-8 或 GBK 都可以。
    可是现在要保留原网站的注册信息。我必须得想办法转化下原来的secret字段。原来的网站数据库字符集是UTF-8 Connection是latin1 前台页面是GBK
    这就是问题的根源…… 痛苦……
      

  6.   

    请问如何将 latin1 编码的字符串以二进制流形式存进 blob字段啊?
      

  7.   

    升级以后不是UTF-8吗?原始的secret是GBK吧,把GBK的转化成UTF-8在导进去.
      

  8.   

    对 cuidenghong123 
       万分感谢!~!你的话提醒了我~!问题解决!
    方法如下:就像把GBK转成UTF-8的方法一样。
    把users表导入。单独改 secret字段的编码为 blob
    再把数据导入。这样 secret字段的值就由字符串转化成了二进制数据。读取时不受 Connection字符集的影响~使用latin1和UTF-8都得出了正确结果。
    用户名为汉字的帐号也能正确登陆了~!哈哈~~谢谢各位!!!!马上给分!
      

  9.   


    这是中间步骤。
    之后再以同样的方法把gbk数据转化成UTF-8数据导入最终的UTF-8数据库中。呵呵。问题解决了,谢谢帮助!
      

  10.   

    总结:整个数据库转化进程如下。
    原始数据库为UTF-8 Connection为Latin1  前台页面为GBK
    数据是以GBK编码保存在UTF-8的数据库中的。
    phpmyadmin显示表中内容为乱码。导出数据
    mysqldump -u root -p --default-character-set=latin1 --set-charset=false tbdev > tbdev_latin1_gbk.sql
    用UltraEdit 将 utf8_general_ci 替换为 gbk_chinese_ci、utf8替换为gbk 保存
    创建GBK数据库: create database tbdev_gbk character set 'gbk' COLLATE 'gbk_chinese_ci'; 
    导入数据到GBK数据库
    mysql -u root -p --default-character-set=gbk tbdev_gbk < tbdev_latin1_gbk.sql
    此时phpmyadmin正确显示汉字。再将GBK编码转化为UTF-8编码mysqldump -u root -p --default-character-set=utf8 --set-charset=false tbdev > tbdev_gbk_utf8.sql
    用UltraEdit 将 gbk 替换为 utf8 保存
    创建UTF-8数据库: create database tbdev_utf8 character set 'utf8' COLLATE 'utf8_general_ci'; 
    导入数据到UTF-8数据库
    mysql -u root -p --default-character-set=utf-8 tbdev_utf8 < tbdev_gbk_utf8.sql
    此时phpmyadmin正确显示汉字。成功将GBK编码转为UTF-8编码。
    但由于secret字段影响,中文帐号无法正常登陆。单独导出users表
    mysqldump -u root -p --default-character-set=utf8 --set-charset=false tbdev_utf8 users > users.sql
    用UltraEdit 将 secret 字段的类型改为 blob 保存
    导入users表到数据库
    mysql -u root -p --default-character-set=utf-8 tbdev_utf8 < users.sql转化完毕。
    经测试,中英文帐户均能正常登陆。且不受 Connection字符集设置影响。
    站点乱码问题解决!在此再次对楼上大虾们的帮助表示感谢!!谢谢!!!!!