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 => true , // 设置数据库连接为持久连接
PDO::ATTR_EMULATE_PREPARES => false , // 防止SQL注入
PDO::ATTR_ORACLE_NULLS => 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() + "&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回复
老师你好,我希望能用一个openwrt路由器实现IPv4和IPv6的桥接,请问我该如何实现?我尝试了直接新增dhcpv6的接口,但是效果不甚理想(无法成功获取公网的ipv6,但是直连上级路由的其他设备是可以获取公网的ipv6地)
![%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE20241205230845.png](https://cdn.wyr.me/visitor-files/2024-12-05/1733411344287屏幕截图 2024-12-05 230845.png)你好
,为什么我这里是0039 813C 0600 0075 16xx xx xx,只有前6组是相同的,博客中要前8位相同,这个不同能不能照着修改呢?我系统版本是Win1124H2
大神你好,win11专业版24h2最新版26100.2033,文件如何修改?谢谢
win11专业版24h2最新版26100.2033,Windows Feature Experience Pack 1000.26100.23.0。C:\Windows\System32\termsrv.dll系统自带的这个文件,39 81 3C 06 00 00 0F 85 XX XX XX XX 替换为 B8 00 01 00 00 89 81 38 06 00 00 90。仍然无法远程连接。原来是win11 21h2系统,是可以远程链接的。共享1个主机,2个显示器,2套键鼠,各自独立操作 各自不同的账号,不同的桌面环境。
博主,win11专业版24h2最新版,C:\Windows\System32\termsrv.dll系统自带的这个文件,找不到应该修改哪个字段。我的微信:一三五73二五九五00,谢谢