在使用php编程的时候,我有一个习惯,不太喜欢使用现成的库文件,例如phplib或者其它类似的库,在这个系统中,我也打算自己写一个库文件,它需要处理认证、确认email,更新帐号(密码,email)等事情。
为了在保证该系统安全的同时,不会加重我现有数据库的负担。因此这个新的系统要依赖cookies。这确实是一个两难的选择,因为如果只是设置一个用户名的cookie,是很不安全的,这行不通,但从数据库的负担考虑,我也不能加入一个简单的无序码而交由我的数据库来进行验证。
解决的方法是同时设置两个cookie,一个是用户名的cookie,一个是无序码的cookie。这个无序码实际上是由用户名和一个超级密码(只有程序设计者知道)组合通过md5()函数运算产生的。由于md5()是一个单向的无序码,因此是不可以破解的。在用户更改email时,我也可以用该email和超级密码产生一个无序码,以让用户确认修改。这实际上是一个公匙/私匙类的系统。不明白?不要紧,下面再慢慢说明。
有趣的是,这个系统的扩展能力是可以达到无穷的,因为该系统的主要工作是计算md5()函数的值,而且由web服务器完成,在负载增加时,可以加入其它的服务器来分担负载,虽然认证系统不会拖跨一个数据库,但是这样做就让最终的瓶颈只能出现在数据库上。
<?php
function user_change_email ($password1,$new_email,$user_name) {
global $feedback,$hidden_hash_var;
if (validate_email($new_email)) {
$hash=md5($new_email.$hidden_hash_var);
file://改变数据库中确认用的无序码值,但不改变email
file://发出一个带有新认证码的确认email
$user_name=strtolower($user_name);
$password1=strtolower($password1);
$sql="update user set confirm_hash='$hash' where user_name='$user_name' and password='". md5($password1) ."'";
$result=db_query($sql);
if (!$result || db_affected_rows($result) < 1) {
$feedback .= ' error - incorrect user name or password ';
return false;
} else {
$feedback .= ' confirmation sent ';
user_send_confirm_email($new_email,$hash);
return true;
}
} else {
$feedback .= ' new email address appears invalid ';
return false;
}
}
function user_confirm($hash,$email) {
/*
用户点击认证email的相关连接时,连到一个确认的页面,该页面会调用这个函数,
*/
global $feedback,$hidden_hash_var;
file://verify that they didn't tamper with the email address
$new_hash=md5($email.$hidden_hash_var);
if ($new_hash && ($new_hash==$hash)) {
file://在数据库中找出这个记录
$sql="select * from user where confirm_hash='$hash'";
$result=db_query($sql);
if (!$result || db_numrows($result) < 1) {
$feedback .= ' error - hash not found ';
return false;
} else {
file://确认email,并且设置帐号为已经激活
$feedback .= ' user account updated - you are now logged in ';
user_set_tokens(db_result($result,0,'user_name'));
$sql="update user set email='$email',is_confirmed='1' where confirm_hash='$hash'";
$result=db_query($sql);
return true;
}
} else {
$feedback .= ' hash invalid - update failed ';
return false;
}
}
function user_send_confirm_email($email,$hash) {
/*
这个函数在首次注册或者改变email地址时使用
*/
$message = "thank you for registering at company.com".
"/nsimply follow this link to confirm your registration: ".
"/n/nhttp://www.company.com/account/confirm.php?hash=$hash&email=". urlencode($email). "/n/nonce you confirm, you can use the services on phpbuilder.";
mail ($email,'registration confirmation',$message,'from:
[email protected]');
}
?>