目录
5.1 我们可以专门建立一个js文件叫loginauto.js文件来进行自动登录的操作
这次笔记是在上次完成注册的功能基础上完成登录以及静默自动登录功能
1 衔接昨天的前端跳转到登录界面
昨天跳转到了登录页面了
//请求提交ajax
$.ajax({
url: `http://localhost:80/users/register?phone=${phone}&code=${code}&nikename=${nikename}&pwd=${password}&repwd=${rePassword}`,
dataType: "json",
type: "get",
success: function (data) {
console.log(data);
let status = data.status;
if (status === 200) {
//请求成功
let faly = confirm("注册成功,是否跳转到登录界面");
if (faly) {
location.href = "loadpage.html";
}
} else {
//请求失败
alert(data.msg);
}
}
});
2 登录页面静态代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/load.css">
</head>
<body>
<header id="headNav">
<div class="innerNav cf">
<a class="fl" href="#"><img src="images/loginlogo.jpg" alt="" /></a>
<div class="headFont fr">
<span>您好,欢迎光临1号店!<a href="registerpage.html">请注册</a></span>
<a class="helpLink" href="#"><i class="runbun"></i>帮助中心<i class="turnb"></i></a>
</div>
<div class="outHelp">
<ul class="helpYou" style="display: none;">
<li><a href="#">包裹跟踪</a></li>
<li><a href="#">常见问题</a></li>
<li><a href="#">在线退换货</a></li>
<li><a href="#">在线投诉</a></li>
<li><a href="#">配送范围</a></li>
</ul>
</div>
</div>
</header>
<section id="secBody">
<div class="innerBody cf">
<img class="fl" src="images/loadimg.jpg" alt="" />
<div class="tableWrap fr">
<div class="tableTap cf">
<h3 class="fl">1号店用户登录</h3>
<a class="fr" href="#">注册账号</a>
</div>
<div class="tableItem">
<i class="userHead"></i>
<!--邮箱、以13、15、18开头的电话或者是2~4个汉字-->
<input type="text" name="userName" placeholder="邮箱/手机/用户名" required />
</div>
<div class="tableItem">
<i class="userLock"></i>
<input type="password" name="password" placeholder="密码" required />
</div>
<div class="tableAuto cf">
<a class="autoMatic fl" href="#"><input class="loadGiet" type="checkbox" />自动登录</a>
<a class="fr" href="#">忘记密码?</a>
</div>
<!--<button class="tableBtn">登录</button>-->
<input type="submit" class="tableBtn" value="登录" />
<h2 class="moreWeb">更多合作网站账号登录</h2>
<div class="outType cf">
<ul class="loadType cf">
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="loadMore fr">更多合作网站<i></i></li>
</ul>
</div>
<ul class="typeWeb cf">
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
</ul>
</div>
</div>
</section>
<footer id="footNav">
<p><a href="#">沪ICP备13044278号</a>| 合字B1.B2-20130004 |<a href="#">营业执照</a></p>
<p>Copyright © 1号店网上超市 2007-2016,All Rights Reserved</p>
</footer>
</body>
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/loadpage.js"></script>
</html>
3 编写前端发送登录请求的程序
<script>
$(function () {
//设置点击事件
$(".tableBtn").click(function () {
//获取登录的值
let username = $("[name='userName']").val();
let pwd = $("[name='password']").val();
//验证数据格式
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(username)) {
alert("手机号码格式不正确");
return;
}
//验证密码不能少于六位
if (pwd.length < 6) {
alert("密码长度不能少于六位");
return;
}
//提交登录请求
$.ajax({
url: `http://localhost:80/users/login?phone=${username}&pwd=${pwd}`,
dataType: "json",
type: "get",
success: function (data) {
处理登录请求后的处理,判断是否登录成功
if (data.status === 200) {
//获取是否自动登录
let checkboxFlay = $(".loadGiet").get(0).checked;
if (checkboxFlay) {
//制作存入localStorage的数组对象
let user = { 'userName': data.msg.userName, 'userPhone': username, 'userPwd': pwd };
//存入localStorage
localStorage.setItem("user", JSON.stringify(user));
}
//登录成功后存入sessionStorage
sessionStorage.setItem("user", JSON.stringify(data.msg));
} else {
alert(data.msg);
}
}
})
});
});
</script>
注意localStorage和sessionStorage的区别;
localStorage是永久存储在本地的
sessionStorage是跟session一个性质,在浏览器关闭或者服务器关闭或者(包的丢失)会清空数据
然后let checkboxFlay = $(".loadGiet").get(0).checked;这里获取复选框的选中状态我这里采用
先用jquery获取复选框,然后转换为js用js中的checked方法来获取的状态,其中获取复选框状态的方法不限于我这一种。
4 编写服务器登录代码
4.1 编写controller登录代码(login)
//登录方法
async function login(req, res) {
//接收参数
let { phone, pwd } = req.query;
//验证参数格式是否正确
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(phone)) {
res.send({ status: 400, msg: "手机号码格式不正确" });
return;
}
//验证密码不能少于六位
if (pwd.length < 6) {
res.send({ status: 400, msg: "密码长度不能少于六位" });
return;
}
//核对数据库数据
let sql = "select userId,userName,userPhone from user where userPhone=? and userPwd=?";
//注意一定要加await等待查询结果出来后再执行下面的代码
let result = await db.opreateDB(sql, [phone, pwd]);
if (result.length === 1) {
//核对只有一条数据且条件正确
//存入session
req.session.islogin = true;
req.session.user = result;
//响应网页
res.send({ status: 200, msg: req.session.user});
} else {
res.send({ status: 400, msg: "登录失败,账号或密码错误" });
}
}
注意:我们在做登录的时候不要把用户的密码响应出去。
4.2 设置路由
router.get('/login', userController.login);
到这里我们的登录方法就完成了,接下来就是自动登录的方法了
5 静默自动登录
5.1 我们可以专门建立一个js文件叫loginauto.js文件来进行自动登录的操作
//此js文件只进行自动登录处理
let user = JSON.parse(localStorage.getItem("user"));
$.ajax({
url: `http://localhost:80/users/login?phone=${user.userPhone}&pwd=${user.userPwd}`,
dataType: "json",
type: "get",
success: function (data) {
//判断是否登录成功
if (data.status === 200) {
//获取是否自动登录
sessionStorage.setItem("user", JSON.stringify(data.msg));
} else {
alert(data.msg);
}
}
})
5.2 静默自动登录的思路
因为我们前面登成功后如果复选框自动登录的选项选择了
那就会把我们的网页上的账号密码存入localStroage本地里面永久保存
这样我们只需要在各个界面引入这个js文件就可以完成自动登录的功能了
<script src="js/loginauto.js"></script>
6 登录功能完整代码
6.1 静态界面完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/load.css">
</head>
<body>
<header id="headNav">
<div class="innerNav cf">
<a class="fl" href="#"><img src="images/loginlogo.jpg" alt="" /></a>
<div class="headFont fr">
<span>您好,欢迎光临1号店!<a href="registerpage.html">请注册</a></span>
<a class="helpLink" href="#"><i class="runbun"></i>帮助中心<i class="turnb"></i></a>
</div>
<div class="outHelp">
<ul class="helpYou" style="display: none;">
<li><a href="#">包裹跟踪</a></li>
<li><a href="#">常见问题</a></li>
<li><a href="#">在线退换货</a></li>
<li><a href="#">在线投诉</a></li>
<li><a href="#">配送范围</a></li>
</ul>
</div>
</div>
</header>
<section id="secBody">
<div class="innerBody cf">
<img class="fl" src="images/loadimg.jpg" alt="" />
<div class="tableWrap fr">
<div class="tableTap cf">
<h3 class="fl">1号店用户登录</h3>
<a class="fr" href="#">注册账号</a>
</div>
<div class="tableItem">
<i class="userHead"></i>
<!--邮箱、以13、15、18开头的电话或者是2~4个汉字-->
<input type="text" name="userName" placeholder="邮箱/手机/用户名" required />
</div>
<div class="tableItem">
<i class="userLock"></i>
<input type="password" name="password" placeholder="密码" required />
</div>
<div class="tableAuto cf">
<a class="autoMatic fl" href="#"><input class="loadGiet" type="checkbox" />自动登录</a>
<a class="fr" href="#">忘记密码?</a>
</div>
<!--<button class="tableBtn">登录</button>-->
<input type="submit" class="tableBtn" value="登录" />
<h2 class="moreWeb">更多合作网站账号登录</h2>
<div class="outType cf">
<ul class="loadType cf">
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="fl"><a href="#"></a></li>
<li class="loadMore fr">更多合作网站<i></i></li>
</ul>
</div>
<ul class="typeWeb cf">
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
<li class="fl"><i></i><a href="#">百度</a></li>
</ul>
</div>
</div>
</section>
<footer id="footNav">
<p><a href="#">沪ICP备13044278号</a>| 合字B1.B2-20130004 |<a href="#">营业执照</a></p>
<p>Copyright © 1号店网上超市 2007-2016,All Rights Reserved</p>
</footer>
</body>
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/loginauto.js"></script>
<!-- <script src="js/loadpage.js"></script> -->
<script>
$(function () {
//设置点击事件
$(".tableBtn").click(function () {
//获取登录的值
let username = $("[name='userName']").val();
let pwd = $("[name='password']").val();
//验证数据格式
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(username)) {
alert("手机号码格式不正确");
return;
}
//验证密码不能少于六位
if (pwd.length < 6) {
alert("密码长度不能少于六位");
return;
}
//提交登录请求
$.ajax({
url: `http://localhost:80/users/login?phone=${username}&pwd=${pwd}`,
dataType: "json",
type: "get",
success: function (data) {
处理登录请求后的处理,判断是否登录成功
if (data.status === 200) {
//获取是否自动登录
let checkboxFlay = $(".loadGiet").get(0).checked;
if (checkboxFlay) {
//制作存入localStorage的数组对象
let user = { 'userName': data.msg.userName, 'userPhone': username, 'userPwd': pwd };
//存入localStorage
localStorage.setItem("user", JSON.stringify(user));
}
//登录成功后存入sessionStorage
sessionStorage.setItem("user", JSON.stringify(data.msg));
} else {
alert(data.msg);
}
}
})
});
});
</script>
</html>
6.2 userController完整代码
//编写跟用户相关的业务操作,注册、登录、修改信息。
const db = require('../util/dbconfig.js');
//登录方法
async function login(req, res) {
//接收参数
let { phone, pwd } = req.query;
//验证参数格式是否正确
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(phone)) {
res.send({ status: 400, msg: "手机号码格式不正确" });
return;
}
//验证密码不能少于六位
if (pwd.length < 6) {
res.send({ status: 400, msg: "密码长度不能少于六位" });
return;
}
//核对数据库数据
let sql = "select userId,userName,userPhone from user where userPhone=? and userPwd=?";
//注意一定要加await等待查询结果出来后再执行下面的代码
let result = await db.opreateDB(sql, [phone, pwd]);
if (result.length === 1) {
//核对只有一条数据且条件正确
//存入session
req.session.islogin = true;
req.session.user = result;
//响应网页
res.send({ status: 200, msg: req.session.user});
} else {
res.send({ status: 400, msg: "登录失败,账号或密码错误" });
}
}
//注册方法
async function register(req, res) {
let { nikename, pwd, repwd, phone, code } = req.query;
//写入数据库的sql语句
let insertsql = "INSERT INTO USER(userName,userPhone,userPwd) VALUES(?,?,?)";
//查重的sql语句
let selectsql = "select count(1) as count from user where userPhone=?";
//查重
let phonecount = await db.opreateDB(selectsql, [phone]);
//存入session的数据
let sessioncode = req.session.code;
let sessionphone = req.session.phone;
//验证手机号码格式
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(phone)) {
res.send({ status: 400, "msg": "手机号码格式不正确" });
return;
}
//验证验证码不等于四以及为字符
if (code.length != 4 || isNaN(code)) {
res.send({ status: 400, "msg": "验证码格式不正确" });
return;
}
//验证昵称不少于三位,最终解释权归程序员所有
if (nikename.length < 3) {
res.send({ status: 400, "msg": "昵称不能少于三位" });
return;
}
//验证密码不能少于六位
if (pwd.length < 6) {
res.send({ status: 400, "msg": "密码长度不能少于六位" });
return;
}
//验证两次密码是否一致
if (pwd != repwd) {
res.send({ status: 400, "msg": "两次密码输入不一致" });
return;
}
//验证注册手机号码是否重复
if (phonecount[0].count > 0) {
res.send({ status: 400, "msg": "手机号码已注册" });
return;
}
//请求的验证码与提交的验证码不一致
if (code != sessioncode) {
res.send({ status: 400, "msg": "验证码错误" });
return;
}
//验证手机号码和提交验证码的手机号码不一致
if (phone != sessionphone) {
res.send({ status: 400, "msg": "手机号码错误" });
return;
}
//数据库注册注册
let count = await db.opreateDB(insertsql, [nikename, phone, pwd]);
/**
* count里面有几个参数
* fieldCount:现场计数
* affectedRows:受影响的行
* insertId:插入Id
* serverStatus:服务器状态
* warningCount:警告计数
* message:消息
* protocol41:协议41
* changedRows:更改的行
*/
//验证是否注册成功
if (count.affectedRows) {
res.send({ status: 200, "msg": "账号注册成功" });
return;
} else {
res.send({ status: 400, "msg": "账号注册失败" });
return;
}
}
//发送验证码方法
async function sendCodeByPhone(req, res) {
//获取手机号码参数
let { phone } = req.query;
//验证手机号码格式
let isphone = /^(0|86|17951)?(13[0-9]|15[012356789]|16[6]|19[89]]|17[01345678]|18[0-9]|14[579])[0-9]{8}$/;
if (!isphone.test(phone)) {
res.send({ status: 400, "msg": "请输入正确的手机号码" });
return;
}
//查询数据库是否重复
let sql = "select count(1) as count from user where userPhone=?";
let count = await db.opreateDB(sql, [phone]);
//验证数据库内是否重复
if (count[0].count > 0) {
//存在就返回已被注册
res.send({ status: 400, "msg": "手机号已被注册" });
} else {
//不存在就存入session,并发送验证码
let code = getCode();
req.session.code = code;
req.session.phone = phone;
res.send({ status: 200, "msg": code });
}
}
//生成1000-9999的随机数
function getCode() {
return Math.floor(Math.random() * 9000 + 1000);
}
//暴露
module.exports = {
sendCodeByPhone,
register,
login
};
6.3 路由完整代码
var express = require('express');
var router = express.Router();
var userController = require('../controller/userController.js');
/* GET users listing. */
router.get('/send', userController.sendCodeByPhone);
router.get('/register', userController.register);
router.get('/login', userController.login);
module.exports = router;
6.4 数据库完整代码
/*
SQLyog Ultimate v12.4.1 (64 bit)
MySQL - 5.7.31-log : Database - liudb
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`liudb` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `liudb`;
/*Table structure for table `user` */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userId` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL,
`userPhone` varchar(11) DEFAULT NULL,
`userPwd` varchar(20) DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
/*Data for the table `user` */
insert into `user`(`userId`,`userName`,`userPhone`,`userPwd`) values
(1,'admin','18888888888','123'),
(3,'dowson','18888888888','123'),
(5,'闫建洲','18216450387','123123');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
7 遇到的问题
今天没什么需要注意的问题,一切基本都能完成,难度不是很大。