当前位置: 首页 > news >正文

网站开发常见问题总结电脑培训班一般多少钱

网站开发常见问题总结,电脑培训班一般多少钱,国家工商网查询官网,企业网站建设的推广方式node后端vue前端实现接口请求时携带authorization验证 我们在写web项目时,后端写好接口,前端想要调用后端接口时,除了登录注册页面,所有的请求都需要携带authorization,这样是为了避免随意通过接口调取数据的现象发生…

node后端+vue前端实现接口请求时携带authorization验证

我们在写web项目时,后端写好接口,前端想要调用后端接口时,除了登录注册页面,所有的请求都需要携带authorization,这样是为了避免随意通过接口调取数据的现象发生。这是写web项目时最基础的点,但是也挺麻烦的,涉及前后端好几个地方的编码,经常忘记怎么写的,现在记录一下。

总体流程如下:

  1. 后端使用中间件开启接口请求验证,除登录/注册外所有接口的请求都需要携带验证参数才能正确发起请求
  2. 前端登录时,存储验证消息,也就是token
  3. 请求拦截器中设置请求头,写入authorization

大体就这么几个步骤,下面细化

一、后端开启接口请求验证

我是用node写的后端,请求验证写在后端入口程序app.js中,完整代码如下:

const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const multer = require("multer");
const upload = multer({ dest: "./public/upload" });
const morgan = require("morgan");
const fs = require("fs");const app = express();// 创建一个写入流,将日志写入access.log文件
const accessLogStream = fs.createWriteStream("./access.log", { flags: "a" });// 使用Morgan中间件,将日志写入控制台和文件
app.use(morgan("combined", { stream: accessLogStream }));app.use(cors());app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.json());// 托管静态文件
app.use(upload.any());
app.use(express.static("./public"));// 处理错误的中间件
app.use((req, res, next) => {res.cc = (err, status = 1) => {res.send({status,message: err instanceof Error ? err.message : err,});};next();
});const jwtconfig = require("./jwt_config/index");
const { expressjwt: jwt } = require("express-jwt");
app.use(jwt({secret: jwtconfig.jwtSecretKey,algorithms: ["HS256"],}).unless({path: [/^\/api\/user\/.*$/],})
);const userManagerRouter = require("./router/user");
app.use("/api/user", userManagerRouter);const userInfoManageRouter = require("./router/userinfo");
app.use("/api/userinfo", userInfoManageRouter);const settingRouter = require("./router/setting");
app.use("/api/setting", settingRouter);const productRouter = require("./router/product");
app.use("/api/product", productRouter);const messageRouter = require("./router/message");
app.use("/api/message", messageRouter);const filesRouter = require("./router/files");
app.use("/api/files", filesRouter);const logRouter = require("./router/log");
app.use("/api/log", logRouter);const overviewRouter = require('./router/overview')
app.use('/api/overview', overviewRouter)// 用户消息读取情况
const dmMsgRouter = require('./router/department_msg')
app.use('/api/dm', dmMsgRouter)// 对不符合joi规则的情况进行报错
// app.use((err, req, res, next) => {
//   if (err instanceof Joi.ValidationError) return res.cc(err.details[0].message);
//   else res.cc(err);
// });app.listen(3088, () => {console.log("api server running at http://127.0.0.1:3088");
});

这个程序太长,相关的代码如下:

const jwtconfig = require("./jwt_config/index");
const { expressjwt: jwt } = require("express-jwt");
app.use(jwt({secret: jwtconfig.jwtSecretKey,algorithms: ["HS256"],}).unless({path: [/^\/api\/user\/.*$/],})
);

其实这个写法相对来说是固定的,首先,导入自己写好的jwt验证规则(也叫秘钥),其实就是一个jwtSecretKey,./jwt_config目录下的index.js文件如下:

module.exports = {jwtSecretKey: 'xxx'  // 改成自己的秘钥
}

然后导入express-jwt,接下来就是使用中间件来设定接口路由规则了,unless方法里面写的是排除的接口地址,是用正则表达式来排除的,/^\/api\/user\/.*$/这个正则表达式的意思是排除所有以/api/user/开头的接口

可以看上面的完整代码,app.use("/api/user", userManagerRouter);这里以/api/user/开头的接口都是给用户登录和注册相关的接口

后端按这个思路写就行了

二、登录存储token

这里有两种存储方式,一种是把token存储在localstorage中,另外一种是存储在全局数据管理工具中(也就是vuex或者pinia中),这里设计前后端联调

1、后端写登录接口,向前端传递token

先看看我的完整的登录接口处理函数

exports.login = (req, res) => {//   res.send("login");const userInfo = req.body;const sql = "select * from users where account = ?";db.query(sql, userInfo.account, (err, results) => {if (err) return res.cc(err);if (results.length !== 1) return res.cc("用户不存在");const compareResult = bcrypt.compareSync(userInfo.password,results[0].password);if (!compareResult) return res.cc("密码错误");// 判断账号是否冻结if (results[0].status == 1) return res.cc("账号被冻结");const user = {...results[0],password: "",imageUrl: "",create_time: "",update_time: "",};const tokenStr = jwt.sign(user, jwt_config.jwtSecretKey, {expiresIn: "10h",});res.send({status: 0,results: results[0],message: '登录成功',token: "Bearer " + tokenStr})});
};

相关的代码如下:

const tokenStr = jwt.sign(user, jwt_config.jwtSecretKey, {expiresIn: "10h",
});
res.send({status: 0,results: results[0],message: '登录成功',token: "Bearer " + tokenStr
})

这里其实很简单,就是后端通过秘钥生成一个有效期为10小时的token,这里的秘钥也是上面提到的,然后向前端发送这个token

2、前端登录时,存储token

我用的vue3,数据存储在pinia中,看看我的前端登录代码

import { useUserStore } from '@/stores/user'
const userStore = useUserStore()const loginCB = async () => {const { account, password } = form.valueconst data = { account, password }loginFormRef.value.validate(async valid => {if (valid) {try {await userStore.getUserInfo(data)// console.log(userStore.userInfo)if (!userStore.userInfo.token) return ElMessage.error('用户名或密码错误')// console.log(userStore.vue3ManageUserInfo)router.push('/')// console.log(results)} catch (error) {ElMessage.error('用户名或密码错误')console.log(error)}} else {ElMessage.error('没通过校验')}})
}

上面这段代码不是完整的,loginCB是登录按钮的回调函数,从回调中看到,其实我的登录是写在pinia的getUserInfo方法中的,继续看看这个store中的写法

import { ref } from "vue";
import { defineStore } from "pinia";
import { loginAPI } from "@/apis/user";
import { getUserInfoAPI } from "@/apis/userinfo";
import { loginLogAPI } from "@/apis/log";export const useUserStore = defineStore("user",() => {const userInfo = ref({});const getUserInfo = async (data) => {const res = await loginAPI(data);// console.log(res);userInfo.value = {account: res.results.account,token: res.token,avatar: res.results.image_url,id: res.results.id,name: res.results.name,sex: res.results.sex,email: res.results.email,department: res.results.department,identity: res.results.identity};// 登录日志await loginLogAPI({account: res.results.account,name: res.results.name,email: res.results.email,});// console.log(userInfo.value)};// 修改头像const changeAvatar = (url) => {userInfo.avatar = url;};// 修改姓名const changeName = (name) => {userInfo.name = name;};//   解决刷新页面丢失store信息的问题const clearUserInfo = () => {userInfo.value = {};};return {userInfo,getUserInfo,clearUserInfo,changeAvatar,changeName,};},{persist: true,}
);

pinia中我用的是组合式api的写法,其实也是比较流行的写法,逻辑和语法都比较清楚

可以看到,我定义了一个userInfo的state,登录需要调用loginAPI,这个接口对应后端的login函数,请求到数据后,将接口返回的token写入到userInfo.token中,这样,全局数据管理store中就存储了一个包含token的名为userInfo的state(真的绕。。。)

注意,组合式api需要将state return出去

  {persist: true,}

上面这个是持久化存储,我在“vue3+pinia用户信息持久缓存(token)的问题”这篇博客中有记录,目的是将userInfo存储到localstorage中

这样,登录时要做的工作就做完了

三、请求拦截器中携带token

使用axios发起接口请求,对axios进行二次封装,封装代码如下:

import axios from "axios";
import { ElMessage } from "element-plus";
import { useUserStore } from "@/stores/user";// 创建axios实例
const http = axios.create({baseURL: "http://127.0.0.1:xxxx/api/", // 改成自己的端口timeout: 5000,
});// axios请求拦截器
http.interceptors.request.use((config) => {const userStore = useUserStore();const token = userStore.userInfo.token;if (token) {config.headers.Authorization = token;}return config;},(e) => Promise.reject(e)
);// axios响应式拦截器
http.interceptors.response.use((res) => res.data,(e) => {ElMessage.warning("接口响应出错");console.log(e);return Promise.reject(e);}
);export default http;

注意看请求拦截器中的代码,用到了刚刚上面提到的pinia中的userInfo这个state,首先获取userInfo中的token,判断是否存在token,存在的话,就把它写到请求头中去,关键的代码就是下面这行:

config.headers.Authorization = token;

这样,每次向后端发起数据请求的时候,都会携带这个token了(除了登录和注册,因为不存在),后端的中间件也能通过验证了


文章转载自:
http://autostoper.yrpg.cn
http://forrader.yrpg.cn
http://underran.yrpg.cn
http://ballast.yrpg.cn
http://rushy.yrpg.cn
http://kuching.yrpg.cn
http://crested.yrpg.cn
http://talmudist.yrpg.cn
http://indiscriminate.yrpg.cn
http://trifacial.yrpg.cn
http://scone.yrpg.cn
http://secern.yrpg.cn
http://surplusage.yrpg.cn
http://dunt.yrpg.cn
http://exanthem.yrpg.cn
http://paracharmonium.yrpg.cn
http://absolvent.yrpg.cn
http://eudemonic.yrpg.cn
http://spinifex.yrpg.cn
http://comedietta.yrpg.cn
http://courtship.yrpg.cn
http://waterscape.yrpg.cn
http://macromere.yrpg.cn
http://clockwork.yrpg.cn
http://excess.yrpg.cn
http://gastricism.yrpg.cn
http://strutbeam.yrpg.cn
http://poppa.yrpg.cn
http://chlamydeous.yrpg.cn
http://linsang.yrpg.cn
http://babycham.yrpg.cn
http://instinctive.yrpg.cn
http://radiogramophone.yrpg.cn
http://pergamum.yrpg.cn
http://bak.yrpg.cn
http://modulate.yrpg.cn
http://hogly.yrpg.cn
http://corticated.yrpg.cn
http://policy.yrpg.cn
http://makeup.yrpg.cn
http://resonator.yrpg.cn
http://gimcrack.yrpg.cn
http://monkish.yrpg.cn
http://rawalpindi.yrpg.cn
http://drawbar.yrpg.cn
http://lifespan.yrpg.cn
http://euphemia.yrpg.cn
http://charmingly.yrpg.cn
http://auxesis.yrpg.cn
http://litterbag.yrpg.cn
http://beadle.yrpg.cn
http://frostbiter.yrpg.cn
http://working.yrpg.cn
http://civics.yrpg.cn
http://carolinian.yrpg.cn
http://reduplicative.yrpg.cn
http://return.yrpg.cn
http://echolocation.yrpg.cn
http://angakok.yrpg.cn
http://earthliness.yrpg.cn
http://continuation.yrpg.cn
http://yami.yrpg.cn
http://presuming.yrpg.cn
http://fichtelgebirge.yrpg.cn
http://matter.yrpg.cn
http://cooner.yrpg.cn
http://amidol.yrpg.cn
http://anticatarrhal.yrpg.cn
http://lallan.yrpg.cn
http://rumorous.yrpg.cn
http://trackless.yrpg.cn
http://margaritic.yrpg.cn
http://chiengmai.yrpg.cn
http://sherlock.yrpg.cn
http://termor.yrpg.cn
http://rocklet.yrpg.cn
http://surfboat.yrpg.cn
http://hypermetric.yrpg.cn
http://turnip.yrpg.cn
http://hermaphroditism.yrpg.cn
http://heterophony.yrpg.cn
http://olim.yrpg.cn
http://desalination.yrpg.cn
http://moue.yrpg.cn
http://fresco.yrpg.cn
http://reconfirmation.yrpg.cn
http://unflinchingly.yrpg.cn
http://revoice.yrpg.cn
http://indefinite.yrpg.cn
http://anchises.yrpg.cn
http://cutlery.yrpg.cn
http://glomma.yrpg.cn
http://parador.yrpg.cn
http://polytocous.yrpg.cn
http://laborious.yrpg.cn
http://tromometer.yrpg.cn
http://sverige.yrpg.cn
http://illumine.yrpg.cn
http://vagal.yrpg.cn
http://norethindrone.yrpg.cn
http://www.dt0577.cn/news/118558.html

相关文章:

  • 柳州做网站网站seo方案案例
  • 网页设计广州网站百度人工客服电话怎么转人工
  • 恒信在线做彩票的是什么样的网站常见的微信营销方式有哪些
  • 网站建设的英文自媒体营销的策略和方法
  • 一个虚拟主机可以做几个网站代做百度收录排名
  • 做网站怎么兼职网络销售话术900句
  • 用一个织梦程序做两个网站营销型网站重要特点是
  • 进入网站服务器怎么做seo关键词优化排名
  • 羽毛球赛事视频网站seo的方法
  • 专业3合1网站建设价格百度指数数据分析平台
  • 图片类网站建设军事网站大全军事网
  • 多语言网站建设平台代理竞价是什么意思
  • 南阳网站推广seo辅助优化工具
  • 有下划线的网址是什么网站seo优化教程下载
  • 京东网站建设思维导图东莞关键词排名快速优化
  • 从做系统网站的收藏怎么找回自己开发网站怎么盈利
  • 手机网站首页布局设计推广之家app下载
  • 上海代办公司注册企业网站排名优化方案
  • 做兼职网站willfast优化工具下载
  • 一般网站建设公司软文营销的宗旨是什么
  • 台州网站建设费用贵阳网站建设
  • 哪些网站可以接工程做排名优化方法
  • 建筑工程网官方网站河南省郑州市金水区
  • 做软件营销网站怎么样重庆seo网络推广平台
  • 不买服务器做网站站长之家seo综合
  • 做网站关键词优化的公司淘宝seo什么意思
  • 做特卖网站有哪些seoul
  • 从零开始制作wordpress主题seo整站优化一年价格多少
  • 几分钟网站做渔网合肥seo外包平台
  • 微信网站页面设计免费招收手游代理