node服务器实现用户登录功能
登录
1.准备登录好前台的ajax
2.后台添加登录的路由配置
2.1响应登录页面
2.2实现登录业务处理
准备登录页面相关资源
1.将login.html页面拷到views目录中
2将admin.css文件拷贝到public/styles目录中
3修改资源的引入
<link rel="stylesheet" href="/styles/bootstrap.css">
<link rel="stylesheet" href="/styles/admin.css">
----------------------------------------------------------
<script src="/libs/jquery.js"></script>
添加登录业务的相关路由配置
//响应登录页面
router.get("/login",(res,req)=>{
handler.login(req,res)
})
//实现登录业务
router.post("/login",(res,req)=>{
handler.userlogin(req,res)
})
应登陆页面
//在handler里处理业务
//响应页面
login:function(req,res){
//读取 登录页面
fs.readFile(path.join(dir__name,"/views/login.html"),(err,data)=>{
if(err){
res.end("404")
}else{
res.end(data)
}
})
}
实现登陆业务
//实现登录业务
userlogin:function(req,res){
//或用户的密码和用户名
let obj=req.body
//根据用户名查询用户信息
let sql=`select * from manager where name=?`
connection.query(sqi,[obj.name],(err,results)=>{
if(err){
console.log(err)
res.json({
code:500,
msg:"服务器蹦了"
})
}else{
//查询成功
判断是否有数据
if(results.length>0){
//判断密码是否与数据库所存的密码一致如果一致则说明密码输入正确
if(results[0].pass==obj.pass){
res.json({
code:200,
msg:"登录成功"
})
}else{
res.json({
code:204,
msg:"密码错误"
})
}
}
//没有查到用户名
else{
res.json({
code: 204,
msg: '用户名输入错误了'
})
}
}
})
}
HTTP的无状态
HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。也就是说在 HTTP 这个 级别,协议对于发送过的请求或响应都不做持久化处理
实现状态保持。常见的实现方式有:cookie,session.token
token实现状态保持的原理
token是服务端生成的一串字符串,以作客户端进行的请求的一个令牌,当第一次登录后,服务器生成一个token便将token返回给客户端,以后客户端只需带上这个token作为之前登陆过的凭证
token不受设备的限制,具有更好的兼容性,同时更安全,
客服端:1接收token实现存储
2请求时传递token
服务器:1.生成token并返回
2.接收token,实现验证
使用token实现状态保持(了解代码)
下载包
npm install jsonwebtoken --save
npm install express-jwt --save
封装token操作
utils/mytoken.js
引入第三方模块:const jwt = require('jsonwebtoken')
生成token
// 生成token
const createToken = function (username) {
// 创建promise对象并返回
return new Promise((resolve, reject) => {
// 调用jwt的sign方法生成token
// jwt.sign(payload,secret,options)
// payload:负载,说白了就是参数,可以是object, buffer或者string
// secret:自定义的密钥
// options:选项,如可以指定加密方式(algorithm:加密算法),也可以指定过期时间(expiresIn:过期时间,以秒表示或描述时间跨度zeit / ms的字符串。如60,"2 days","10h","7d")
const token = jwt.sign({
name: username
}, secretkey, { expiresIn: '10h' });
// 生成成功调用resolve方法
resolve(token);
})
}
暴露成员
module.exports={
createToken,
verifyToken
}
后台
//handler.js
//引入token
const mytoken=requier("./utils/mytoken.js")
if(data.password==obj.password){//登陆成功
//生成token
mytoken.createToken(data.userName)
.then((token)=>{
res.json({
code:200,
msg:'登陆成功',
token
})
})
}
添加中间件,校验token
//没有规定请求方式,也没有规定路由,那么所有请求都会会经过这个中间键
//app.js
app.use(function(req,res,next){
//获取请求头传递过来的token数据,这里也说明了,客户端传递token数据要在请求头中添加Authorization的设置,用来传递token数据
let token=req.headers["authorization"];
//如果没有token
if(token==undefined){
return next()
}else{
//如果有token
mytoken.verifyToken(token).then((data)=>{
req.data="data"
retyrn next();
}).catch((error)=>{
return next();
})
}
})
置不需要token校验的路由
// expressJwt:使用这个模块方法可以设置那些path不需要进行token验证
app.use(expressJwt({
secret: 'hero',
// 6.0之后一定要设置算法,否则报错:algorithms should be set
algorithms:['HS256']
}).unless({
path: ['/login']//除了这个地址,其他的URL都需要验证
}));
添加错误处理中间件
app.use(function(err,req,res,next){
if(err.name==="UnauthorizedError"){
res.json({
message: 'token过期,请重新登录',
code: 400
})
}
})
前台–掌握
登陆成功接收token并存储
$("#btn").on("click",function(){
$.ajax({
type:"post",
url:"http://127.0.0.1:3002/login",
data:$(form).serialize(),
dataType:"json"
success:function(res){
console.log(res)
if(res.code==200){
//把从服务器拿到的token存储在本地
localStorage.setItem("hero_token_54",res.token)
//跳转到主页面
location.href="/"
}else{
alert(res.msg)
}
}
})
})
后续请求传递token
function init(){
$.ajax({
url:"http://127.0.0.1:3002/getalldata",
dataType:"json",
headers:{
Authorization:'Bearer '+localStorage.getItem('hero_token_54')
},
success:function(res){
conlose.log(res)
if(res.code==200){
//动态渲染
$('tbody').html(template('herosTemp',res))
}else if(res.code==400){
location.herf="/login"
}
}
}