轶哥

📚 Having fun with AI Agent. Always learning.

    HTML5用户身份认证源代码:注册、登录、会话保持的解决方案

      本文是针对PHP新手的Session教程 —— 用户注册、登录、身份认证。以下代码均为伪代码,正式项目中需要修改完善强化其安全性。

    MySQL数据库管理员表 admin.sql

    # table admin
    # ------------------------------------------------------------
    
    CREATE TABLE `admin` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `username` varchar(30) DEFAULT NULL,
      `password` varchar(500) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    INSERT INTO `admin` (`id`, `username`, `password`)
    VALUES
        (1,'admin','admin');
    

    用户注册表单 register.html

    <form id="user_register">
    <label for="input_Username">用户名</label>
    <input type="text" id="input_Username" name="input_Username" placeholder="用户名" required autofocus>
    <label for="input_Password">密码</label>
    <input type="password" id="input_Password" name="input_Password" placeholder="密码" required>
    <button type="button" id="button_register">注册</button>
    </form>
    

    用户注册Ajax代码 register.js

    $("#button_register").click(function () {
            $.ajax({
                cache: false,
                url:"php/register.php",
                type: "POST",
                async: false,
                data:$("#user_register").serialize(),
                dataType:"json",
                success: function(data){
                    //处理返回结果
                    switch(data.error){
                        case "false":
                            alert("注册成功!" + "注册的用户ID为:" + data.user_id);
                            break;
                        case "Insert error":
                            alert("数据写入失败,请联系管理员");
                            break;
                        case "Username exist":
                            alert("用户名已经存在");
                            break;
                        default:
                            alert("注册出错,请联系管理员");
                    }
                },
                error: function (data) {
                    alert("数据获取失败,请检查网络连接。" );
                    console.info(data);
                }
            });
    });
    

    PHP数据库连接文件 connect.php

    <?php
    /**
    
    
    数据库连接文件
    *
    
    PDO连接MySQL数据库
    
    @author      王轶<a@wyr.me>
    
    @version     0.1
    
    @copyright   BSD
    */
    try {
     $db_ip = "localhost";   //数据库IP地址
     $db_name = "";          //数据库名称
     $db_user = "";          //数据库用户名
     $db_pass = "";          //数据库密码
     $PDO = new PDO('mysql:host='.$db_ip.';dbname='.$db_name, $db_user, $db_pass, array(
     PDO::ATTR_PERSISTENT =&gt; true , // 设置数据库连接为持久连接
     PDO::ATTR_EMULATE_PREPARES =&gt; false , // 防止SQL注入
     PDO::ATTR_ORACLE_NULLS =&gt; true , // 设置当字符串为空转换为 SQL 的 NULL
     PDO::ATTR_ERRMODE , // 设置抛出错误
     PDO::ERRMODE_EXCEPTION // 设置抛出错误
     ));//PDO数据库连接代码
    } catch (PDOException $e) {
     print "Error!: " . $e->getMessage() . "<br/>";
     die();
    }
    
    
    /**
    
    
    格式化SQL数据类型
    *
    
    @param string $theValue 目标SQL数据类型
    
    @param mixed $theType 传入需要变更类型的数据
    
    @return mixed
    */
    function GetSQLValueString($theValue, $theType)
    {
     switch ($theType) {
     case "text":
         $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
         break;
     case "long":
     case "int":
         $theValue = ($theValue != "") ? intval($theValue) : "NULL";
         break;
     case "double":
         $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
         break;
     case "date":
         $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
         break;
     }
     return $theValue;
    }
    

    用户注册后端处理PHP代码 register.php

      其它语言相似,判断处理后返回json。

    <?php
    require_once("connect.php");//加载数据库连接文件
    //判断是否接收到了表单数据
    if(isset($_POST["input_Username"])) {
        //写入数据前检测用户名是否存在
        $username = $_POST["input_Username"];
        $Check_Username = $PDO->query("SELECT id FROM admin WHERE username=".GetSQLValueString($username, "text"));
        $Check_Username_result = $Check_Username->fetch(PDO::FETCH_ASSOC);
        if ($Check_Username_result["id"] == null) {
            //如果用户名不存在
            $password = md5(md5("aq1ja".$_POST['input_Password']."jfsah2"));//第一次执行md5的时候在前后加上安全码,再次执行md5防止md5破解
            //这个方法虽然能够加强密码强度防止暴力破解,但有弊端,仅供参考
            $insertSQL = sprintf("INSERT INTO admin SET username = %s, password = %s",
                GetSQLValueString($username, "text"),
                GetSQLValueString($password, "text"));
            $Result = $PDO->exec($insertSQL);//执行数据库写入操作
            $back_id = $PDO->lastInsertId();//获取写入的数据id
            if ($Result == "1") {//如果成功写入一条数据
                $doc = array("error" => "false", "user_id" => $back_id);//返回当前注册用户的id,可能其它业务逻辑需要
            } else {
                $doc = array("error" => "Insert error");
            }
        }else{
            $doc = array("error" => "Username exist");//返回错误提示:用户名已经存在
        }
    }else{
        $doc = array("error" => "Illegal request");//没有接收到POST过来的表单数据,有可能是非法访问
    }
    
    $PDO = null;//关闭数据库链接
    echo json_encode($doc);//返回为json字符串
    

    用户登录表单 sign.html

    <form id="user_sign">
        <label for="input_Username" class="sr-only">用户名</label>
        <input type="text" id="input_Username" name="input_Username" placeholder="用户名" required autofocus>
         <label for="input_Password" class="sr-only">密码</label>
         <input type="password" id="input_Password" name="input_Password" placeholder="密码" required>
         <div class="checkbox">
               <label>
                      <input type="checkbox" name="remember_me" value="remember-me"> 保持登录状态
               </label>
         </div>
         <button type="button" id="button_sign">登录</button>
    </form>
    

    用户登录Ajax代码 sign.js

            //用户登录按钮按下-提交登录表单:
            $("#button_sign").click(function () {
                $.ajax({
                    cache: false,
                    url: "php/sign.php",
                    type: "POST",
                    async: false,
                    data: $("#user_sign").serialize() + "&sign=on",//sign=on是登录,sign=off是注销
                    dataType: "json",
                    success: function (data) {
                        //处理返回结果
                        switch (data.error) {
                            case "false":
                                if (window.sessionStorage && window.localStorage) {
                                    if(data.type == "time_on"){
                                        window.localStorage["user_access"] = data.user_access;
                                    }else{
                                        window.sessionStorage["user_access"] = data.user_access;
                                    }
                                    alert("登录成功!" + "返回的随机字符串是:" + data.user_access);
                                } else {
                                    alert("浏览器不支持localStorage或sessionStorage,换chrome吧");
                                }
                                break;
                            case "Username or Password error":
                                alert("用户名或密码错误");
                                break;
                            default:
                                alert("登录出错,请联系管理员");
                        }
                    },
                    error: function (data) {
                        alert("数据获取失败,请检查网络连接。");
                        console.info(data);
                    }
                });
            });
    

    用户登录后端处理 sign.php

    <?php
    require_once("connect.php");//加载数据库连接文件
    session_start(); //标志Session的开始
    //判断是否接收到了表单数据
    if(isset($_POST["sign"]) && $_POST["sign"] == "on") {
        date_default_timezone_set("PRC");
        $select = $PDO -> query("SELECT * FROM admin WHERE username = ".GetSQLValueString($_POST["input_Username"], "text"));
        $back = $select -> fetch(PDO::FETCH_ASSOC);
        if($back["username"] == $_POST["input_Username"] && $back["password"] == md5(md5("aq1ja".$_POST['input_Password']."jfsah2"))){
            $_SESSION["username"] = $back["username"];
            $_SESSION["user_id"] = $back["id"];
            $_SESSION["star_time"] = time();
            $_SESSION["user_access"] = (string)md5(rand(100000,999999)."wiq");//生成一个随机字符串
            if(isset($_POST["remember_me"]) && $_POST["remember_me"] == "remember-me"){
                //$doc = array("error" => "false" , "type" => "time_on" , "user_access" => $_SESSION["user_access"]);这里的user_access需要写入数据库
            }else{
                $doc = array("error" => "false" , "type" => "time_off", "user_access" => $_SESSION["user_access"]);
            }
        }else{
            $doc = array("error" => "Username or Password error");
        }
    }else if(isset($_POST["sign"]) && $_POST["sign"] == "off"){
        unset($_SESSION["username"]);
        unset($_SESSION["user_access"]);
        unset($_SESSION["user_id"]);
        unset($_SESSION["star_time"]);
        $doc = array("error" => "false");
    }else{
        $doc = array("error" => "Illegal request");//没有接收到POST过来的表单数据,有可能是非法访问
    }
    
    $PDO = null;//关闭数据库链接
    echo json_encode($doc);//返回为json字符串
    

    用户身份认证前端代码

    <div id="show_on" style="display: none">
        <p id="show_text"></p>
        <a href="sign.html?sign=off">注销</a>
    </div>
    
            //判断在线状态:
            if (window.sessionStorage && window.localStorage) {
                function sign(user_access,type){
                    $.ajax({
                        cache: false,
                        url: "php/access.php",
                        type: "POST",
                        async: false,
                        data: {"user_access":user_access},
                        dataType: "json",
                        success: function (data) {
                            //处理返回结果
                            switch (data.error) {
                                case "false":
                                    $("#show_on").show();
                                    $("#user_sign").hide();
                                    $("#show_text").text("身份认证成功!当前用户:" + data.username + " id: " + data["user_id"]);
                                    break;
                                case "No_time":
                                    if(type == "session"){
                                        window.sessionStorage.removeItem("user_access");
                                    }else{
                                        window.localStorage.removeItem("user_access");
                                    }
                                    alert("身份认证过期,请重新登录");
                                    break;
                                default:
                                    alert("数据出错,请联系管理员");
                            }
                        },
                        error: function (data) {
                            alert("数据获取失败,请检查网络连接。");
                            console.info(data);
                        }
                    });
                }
                var session = window.sessionStorage;
                if(session["user_access"]){
                    sign(session["user_access"],"session");
                }else if(window.localStorage["user_access"]){
                    sign(window.localStorage["user_access"],"local");
                }
            } else {
                alert("浏览器不支持localStorage或sessionStorage,换chrome吧");
            }
    

    注销代码

    $(function () {
            //获取URL中的参数 [分析GET过来的数据]
            function get(name){
                var geturl = window.location.search.substr(1).split("&");
                for(var n=0;n<geturl.length;n++){
                    if(decodeURIComponent(name)==geturl[n].split("=")[0]){
                        return decodeURIComponent(geturl[n].split("=")[1]);
                    }
                }
            }
    
        //注销:
        if(get("sign") == "off"){
            $.ajax({
                cache: false,
                url: "php/sign.php",
                type: "POST",
                async: false,
                data: $("#user_sign").serialize() + "&amp;sign=off",//sign=on是登录,sign=off是注销
                dataType: "json",
                success: function (data) {
                    //处理返回结果
                    switch (data.error) {
                        case "false":
                            alert("注销成功!");
                            break;
                        default:
                            alert("注销出错,请联系管理员");
                    }
                },
                error: function (data) {
                    alert("数据获取失败,请检查网络连接。");
                    console.info(data);
                }
            });
        }
    })
    

    用户身份认证后端代码 access.php

    <?php
    session_start(); //标志Session的开始
    error_reporting(0);//屏蔽报错
    date_default_timezone_set("PRC");
    if(isset($_POST["user_access"]) && $_POST["user_access"] == $_SESSION["user_access"]){
        if(time() - $_SESSION["star_time"] < 21600){
            $doc = array("error" => "false" , "username" => $_SESSION["username"], "user_id" => $_SESSION["user_id"]);
            //在这里编写认证后的业务逻辑
        }else{
            $doc = array("error" => "No_time");
        }
    } else {
        $doc = array("error" => "No_time");
    }
    echo json_encode($doc);//返回为json字符串
    

    代码使用说明

      以上代码仅为简单实例,这只是一个解决方案。安全性上还需要进一步完善。需要特别注意的是,上面的代码中的身份认证在用户关闭浏览器后随即失效,没有实现登录状态的长期保持,可以使用localStorage来保存本地的随机码(需要处理数据库配合)。在用户身份认证的时候比对数据库里面的信息判断localStorage中的随机码是否失效。

    打赏
    交流区(3)
    @

    🥺

    2015年11月21日 05:38回复
    轶哥

    ☺️

    2015年11月21日 07:35回复
    杨桥

    😲

    2015年11月23日 08:00回复
    尚未登陆
    发布
      上一篇 (C#扫描在线IP源代码-多媒体教室、公司内网管理IP搜索)
    下一篇 (发展中的云计算)  

    评论回复提醒