一个完整、安全的PHP用户登录系统

 更新时间:2016年11月25日 15:17  点击:1411

在使用PHP 编程的时候,我有一个习惯,不太喜欢使用现成的库文件,例如PHPLib或者其它类似的库,在这个系统中,我也打算自己写一个库文件,它需要处理认证、确认email ,更新帐号(密码,email )等事情。

    为了在保证该系统安全的同时,不会加重我现有数据库的负担。因此这个新的系统要依赖cookies.这确实是一个两难的选择,因为如果只是设置一个用户名的cookie,是很不安全的,这行不通,但从数据库的负担考虑,我也不能加入一个简单的无序码而交由我的数据库来进行验证。

    解决的方法是同时设置两个cookie,一个是用户名的cookie,一个是无序码的cookie. 这个无序码实际上是由用户名和一个超级密码(只有程序设计者知道)组合通过md5 ()函数运算产生的。由于md5 ()是一个单向的无序码,因此是不可以破解的。在用户更改email 时,我也可以用该email 和超级密码产生一个无序码,以让用户确认修改。这实际上是一个公匙/ 私匙类的系统。不明白?不要紧,下面再慢慢说明。

    有趣的是,这个系统的扩展能力是可以达到无穷的,因为该系统的主要工作是计算md5 ()函数的值,而且由web 服务器完成,在负载增加时,可以加入其它的服务器来分担负载,虽然认证系统不会拖跨一个数据库,但是这样做就让最终的瓶颈只能出现在数据库上。

    以下是该库中的两个函数——记号产生和记号认证函数。
   
    <?php

   $hidden_hash_var='your_secret_password_here';

   $LOGGED_IN=false;
   
      unset($LOGGED_IN);

   function user_isloggedin() {
   
     global $user_name,$id_hash,$hidden_hash_var,$LOGGED_IN;
 
   file://已经进行无序码的检测了吗

   file://如果是的话,返回该变量

   if ( isset($LOGGED_IN) ) {

   return $LOGGED_IN;

   }

   file://are both cookies present?

   if ($user_name && $id_hash) {

   /*
       
      由cookies中得来的用户名和系统超级密码产生一个认证用的无序码如果该无序码与cookie中的无序码一样,则cookies中的变量是可信的,用户已经登录

   */

   $hash=md5($user_name.$hidden_hash_var);

   if ($hash == $id_hash) {

   file://无序码符合,设置一个全局变量,这样我们在再次调用该函数的时候,

   file://就无需再次进行md5()运算

   $LOGGED_IN=true;

   return true;

   } else {

   file://两个无序码不符合,没有登录

   $LOGGED_IN=false;

   return false;

   }

   } else {

    $LOGGED_IN=false;

    return false;

   }

    }

   function user_set_tokens($user_name_in) {

   /*

   一旦用户名和密码通过验证,就调用这个函数

   */

   global $hidden_hash_var,$user_name,$id_hash;

   if (!$user_name_in) {

   $feedback .= ' ERROR - User Name Missing When Setting Tokens ';

   return false;

   }

   $user_name=strtolower($user_name_in);

   file://使用用户名和超级密码创建一个无序码,作判断是否已经登录用

   $id_hash= md5($user_name.$hidden_hash_var);

   file://设置cookies的有效期为一个月,可设置为任何的值

   setcookie('user_name',$user_name,(time()+2592000),'/','',0);

   setcookie('id_hash',$id_hash,(time()+2592000),'/','',0);

   }

   ?>

再来看另一段有趣的代码,用户怎样才能安全地改变他们的email地址呢?他们可以在任何时候改变email地址,但是要进行确认。

   <?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: ".
      
       "nnhttp://www.company.com/account/confirm.php?hash=$hash&email=". urlencode($email). "nnOnce you confirm, you can use the services on PHPBuilder.";

        mail ($email,'Registration Confirmation',$message,'From: noreply@company.com');

      }

    ?>

Call to undefined function mysql_connect()

很多初学者都经常碰到这种问题,但对老鸟来说这不是什么问题了,仔细分析一下就知道是mysql.dll文件没存在,或没有把php.ini里面的.extension=php_mysql.dll前面的; 去了.

php.ini的everyone权限不够,给php.ini文件增加everyone的所有权先后问题解决。

问题其实很简单的,可能还有一些其他的问题,各位要根据自己的具体情况去解决问题了.

 

 

数据插不进数据库

 

解决办法:

1.创建数据库,我们在整理的选项中选择的是utf-8字符集,那么我们的php网页中就要charset改为这样<meta http-equiv="Content-Type" content="text/html; charset=utf-8">,同时我们的操作数据库语句(select,insert等)前要加上 mysql_query("SET NAMES 'utf8'");

2.创建数据库,我们在整理的选项中选择的是gb2312字符集,那么我们的php网页中就要charset改为这样<meta http-equiv="Content-Type" content="text/html; charset=gb2312">,同时我们的操作数据库语句(select,insert等)前要加上 mysql_query("SET NAMES 'gb2312'");

3.如果你的数据库字段创建时是gb2312那面连接时数据就得mysql_query("set Names gb2312"),

4.还有一种办法就是用函数转换,iconv('被转换的','转换成的',要转换的符)

正则表达式  模式匹配 Javascript
摘要:收集一些常用的正则表达式。
正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。本贴随时会更新。

匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g  //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]

var s="abacabefgeeii"
var s1=s.replace(/(.).*\1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2)  //结果为:abcefgi

我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="http://www.9499.net/page1.htm"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

利用正则表达式限制网页表单里的文本框输入内容:

用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

用session进行登录验证

页面1:

<html>
<title>Login Test</title>
<body>

<?php
if(empty($_POST['user']))
{
?>
<form action="<?php $PHP_SELF ?>" method=POST >
UserName:<input type="text" name="user" />
</br>
Password:<input type="password" name="pwd" />
<input type="submit" />
</form>
<?php
}
else
{
$user=$_POST['user'];
$pwd=$_POST['pwd'];
if($user=="test"&&$pwd=="test")
{
echo "success";
session_start();
$_SESSION['user']=$user;
header('Location:页面2');
}
}
?>
</body>
</html>


页面2:

<?php
session_start();
if(!empty($_SESSION['user']))
{
echo "success";
}
else
{
echo "Login Please!";
}
?>

[!--infotagslink--]

相关文章

  • php 获取用户IP与IE信息程序

    php 获取用户IP与IE信息程序 function onlineip() { global $_SERVER; if(getenv('HTTP_CLIENT_IP')) { $onlineip = getenv('HTTP_CLIENT_IP');...2016-11-25
  • 详解前端安全之JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
  • php简单用户登陆程序代码

    php简单用户登陆程序代码 这些教程很对初学者来讲是很有用的哦,这款就下面这一点点代码了哦。 <center> <p>&nbsp;</p> <p>&nbsp;</p> <form name="form1...2016-11-25
  • php根据用户语言跳转相应网页

    当来访者浏览器语言是中文就进入中文版面,国外的用户默认浏览器不是中文的就跳转英文页面。 <&#63;php $lan = substr(&#8194;$HTTP_ACCEPT_LANGUAGE,0,5); if ($lan == "zh-cn") print("<meta http-equiv='refresh' c...2015-11-08
  • js检测用户输入密码强度

    一个用Javascript检测用户输入密码强度的效果代码,以下代码主要是从以下四个方面检测用户输入的密码的强度的,有兴趣的朋友可以自己添加或修改成自己想要的形式! 1. 如果输入的密码位数少于5位,那么就判定为弱。 2. 如果...2015-10-23
  • php有效防止同一用户多次登录

    【问题描述】:同一用户在同一时间多次登录如果不能检测出来,是危险的。因为,你无法知道是否有其他用户在登录你的账户。如何禁止同一用户多次登录呢? 【解决方案】 (1) 每次登录,身份认证成功后,重新产生一个session_id。 s...2015-11-24
  • vue实现用户登录切换

    这篇文章主要为大家详细介绍了vue实现用户登录切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-04-22
  • 安全地关闭MySQL服务的教程

    普通关闭 我的mysql是自己下载的tar包,自己设定安装目录来安装的。停止mysql服务,说来简单,但不知道的话,还真是挠头。在这和mysql入门的同学们共享:)正确方法是,进入mysql的bin目录下,然后执行./mysqladmin -uroot -p shut...2015-11-24
  • php ajax注册验证用户名是否存在代码

    这是注册程序是一款当用户输入完用户名是,就会自动去数据库中查询用户要注册的用户名是否己经被注册了,如果是返回提示否则提示可以注册。 conn.php文件 代...2016-11-25
  • C#实现线程安全的简易日志记录方法

    这篇文章主要介绍了C#实现线程安全的简易日志记录方法,比较实用的功能,需要的朋友可以参考下...2020-06-25
  • 微信小程序用户授权最佳实践指南

    这篇文章主要给大家介绍了关于微信小程序用户授权最佳实践的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-08
  • apache中配置整合tomcat环境与安全配置

    系统:centos 5.9 环境:apache 2.2.25 tomcat 7.0.42 jdk 1.7.0 1.安装apache 我这里是直接yum安装的,如果你们要编译安装也不是不行. 代码如下 ...2016-01-28
  • PHP中如何使用session实现保存用户登录信息

    session在php中是一个非常重要的东西,像我们用户登录一般都使用到session这个东西,相对于cookie来说session 要安全很多,同时我们购物车经常使用session来做临时的记录保存哦。使用session保存页面登录信息1、数据库连接...2015-10-21
  • 简单php cookie用户登录实例

    cookie 的用途之一是存储用户在特定网站上的密码和 id。另外,也用于存储起始页的首选项。在提供个人化查看的网站上,将要求阁下的网络浏览器利用阁下计算机硬驱上的少量...2016-11-25
  • 超详细的php用户注册页面填写信息完整实例(附源码)

    注册页面是大多数网站必备的页面,所以很有必要对自己的注册页面做些精心的设计。下面三张图,第一张是注册的展示页面,第二张思维导图就一个简单的逻辑,第三张是通过firebug查看调用的JS文件。 一、给每个输入框写下说明在...2015-11-24
  • MySQL验证用户权限的方法

    知识归纳因为MySQL是使用User和Host两个字段来确定用户身份的,这样就带来一个问题,就是一个客户端到底属于哪个host。 如果一个客户端同时匹配几个Host,对用户的确定将按照下面的优先级来排 基本观点越精确的匹配越优先...2015-11-08
  • sqlserver添加sa用户和密码的实现

    这篇文章主要介绍了sqlserver添加sa用户和密码的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-07
  • 如何有效提高网站的用户回头率

    第一,网站的内容;请各位站长朋友不要一天到晚只想着出什么好的绝招来推广网站,却忽略了网站的内容;其实网站的内容是极为重要的,因为这是你的本,你的根!网站的内容只有不断...2017-07-06
  • MySQL数据库安全设置和常用管理方式

    当你第一次在机器上安装MySQL时,mysql数据库中的授权表是这样初始化的:你可以从本地主机(localhost)上以root连接而不指定口令。root用户拥有所有权限(包括管理权限) 并可做任何事情。...2013-09-19
  • mysql误删root用户恢复方法

    装完数据库清理一些默认账号的时候不小心把root删除了,flush privileges 之后的新 root 忘了grant任何权限,查看mysqld选项里面有个 &#8722;&#8722;skip-grant-tables复制代码 代码如下: #/usr/libexec/mysqld --verbos...2015-03-15