nodejs框架express使用jwt控制权限

思路:用户调用后端登录接口,后端获取到正确的用户名密码后,给response的header设置Authorization属性值,值为通过jwt生成的token值,前端登录成功后,拿到token并存入storage中,在后续请求的时候,在请求头的authorization带上token信息,如果后端在拿到请求提的时候获取不到token,会自动重定向到login页面

项目地址:GitHub - Rose-chen/express-jwt: nodejs框架express使用jwt控制权限

  • 创建数据库连接

安装使用mongoose模块

npm i mongoose -S

根目录下创建config文件夹,新建文件db.config.js

创建连接

const mongoose = require('mongoose')
//连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/test-node')
//插入集合和数据,数据库test-node会自动创建

//监听数据库连接状态
mongoose.connection.once('open',()=>{
  console.log('数据库连接成功……')
})
mongoose.connection.once('close',()=>{
  console.log('数据库断开……')
})

在bin文件夹的www文件中引入

require('./../config/db.config')
  • 创建数据模型

根目录下创建models文件夹

新建文件UserModel.js

const mongoose = require('mongoose')
const Schema = mongoose.Schema
const UserType = new Schema({
  username: String,
  password: String,
  age: Number
})
//数据字段可根据实际需求修改

const UserModel = mongoose.model('users', UserType)
//此处users名称需要跟数据库中对应集合名称一样

module.exports = UserModel
  • 后端处理路由

用户登录接口,使用mongoose的find方法匹配用户

router.post('/login', async function(req, res, next) {
  // console.log(req)
  const { username, password } = req.body;
  const resp = await UserModel.find({ username, password})
  // 如果查询到数据,resp为对象数组
  if(resp.length) {
    res.send({
      ok: 1
    })
  } else {
    res.send({
      ok: 0
    })
  }
})

用户登录成功后,给req的headers设置Authorization属性

JWT.js代码

const jwt = require('jsonwebtoken')
const secret = 'chen-anydata'
const JWT = {
  generator(data, expries) {
    return jwt.sign(data, secret, {expiresIn: expries})
  },
  verify(data) {
    return jwt.verify(data, secret)
  }
}

module.exports = JWT

/api/login接口新增JWT相关代码

router.post('/login', async function(req, res, next) {
  // console.log(req)
  const { username, password } = req.body;
  const resp = await UserModel.find({ username, password})
  // 如果查询到数据,resp为对象数组
  if(resp.length) {
    const token = JWT.generator({
      id: resp[0]._id,
      username: resp[0].username,
    }, 30)
    res.header('Authorization', token)
    res.send({
      ok: 1
    })
  } else {
    res.send({
      ok: 0
    })
  }
})

前端登录界面/login调用登录

//axios封装
axios.interceptors.request.use(function (config) {
		    	return config;
		}, function (error) {
			return Promise.reject(error);
		});

		axios.interceptors.response.use(function (response) {
			// console.log(response.headers)
			const { authorization } = response.headers
			authorization && localStorage.setItem("token", authorization)
			return response.data;
		}, function (error) {
			return Promise.reject(error);
		});

//登录请求
axios.post("/api/login", {
					username: username.value,
					password: password.value,
				}
			).then(res => {
				console.log(res)
				if (res.ok === 1) {
					alert('登录成功')
					location.href= "/"
				} else {
					alert("用户名密码不匹配")
				}
			})

前端首页/index

//拿到storage里的token,并在请求的headers中设置Authorization 
axios.interceptors.request.use(function (config) {
        const token = localStorage.getItem('token');
        config.headers.Authorization = token;
        return config;
      }, function (error) {
        return Promise.reject(error);
      });
  
axios.interceptors.response.use(function (response) {
        const { authorization } = response.headers
        authorization && localStorage.setItem("token", authorization)
        return response.data;
      }, function (error) {
        if(error.response.status===401){
          localStorage.removeItem("token")
          location.href = "/login"
        }
        return Promise.reject(error);
      });

//获取用户列表
axios.get("/api/user?page=1&limit=10").then(res=>{
          if(res.ok===0){
              location.href="/login"
            }
          var tbody = document.querySelector("tbody")
          tbody.innerHTML = res.map(item=>`
            <tr>
              <td>${item._id}</td>  
              <td>${item.username}</td>  
              <td>${item.age}</td>  
            </tr>
          `).join("")
        })

对应/api/user接口后端代码

router.get('/user', async function(req, res, next) {
  const { page, limit } = req.query;
  const resp = await UserModel.find({}, ['username', 'age']).sort({age: -1}).skip((page-1)*limit).limit(page*limit)
  res.send(resp)
});

app.js中,使用中间件,检验token

//设置中间件,校验token
app.use((req, res, next) => {
  //排除不需要校验的路由
  if(req.path.includes('/login') || !req.path.includes('/api')) {
    next()
    return
  }

  const token = req.headers['authorization']
  if(token) {
    try {
      const payload = JWT.verify(token)
      console.log('payload',payload)
      if(payload) {
        const newtoken = JWT.generator({
          id: payload._id,
          username: payload.username,
        }, 30)
        res.header('Authorization', newtoken)
        next()
      } else {
        res.status(401).send({errCode: -1, errMsg: 'token过期'})
      }
    } catch {
      res.status(401).send({errCode: -1, errMsg: 'token过期'})
    }
  } else {
    res.status(401).send({errCode: -1, errMsg: 'token过期'})
  }
})

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值