总体流程:
1.在登录页面中的登录方法将账号密码发给后台进行校验,校验成功后将后台返回的token存到浏览器本地(存到哪里,自己根据自己的实际业务来, 我以存到sessionStorage为例)
2.在路由中设置一下前置守卫拦截器,判断跳转路由时sessionStorage存储的token是否为空,为空则调到登录页面
3.设置每次向后台请求时从sessionStorage存储的token带上传给后台,因为后台需要校验
登录页面
<template>
<div>
<h1>我是登录页面</h1>
<p>账号:<input type="text" v-model.trim="username"></p>
<p>密码:<input type="text" v-model.trim="password"></p>
<p>
<button @click="logined">登录</button>
</p>
</div>
</template>
<script>
import request from "@/utils/request"; // 这是我自己对axios进行封装的,在文章的最后面会贴出代码
export default {
name: "login.vue",
data () {
return {
username: "yykk",
password: "123456"
}
},
methods: {
logined () {
let userName = this.username;
let password = this.password;
request.post("/login/account/pwd", { userName, password }).then(res => {
if (res.status == 200) {
// 把服务器段信息放入到session中
sessionStorage.setItem("token", res.data);
// 这个back是为了用户登录后可以直接跳转到想要去的页面,在路由配置的js文件中有设置
var back = this.$route.query.back || "/";
this.$router.push(back);
}
}).catch(err => {
console.error("登录失败!!!", err)
})
}
}
}
</script>
<style scoped>
</style>
路由拦截(router的js文件)
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: "/",
name: "layout",
component: () => import('@/layout/Layout'),
redirect: "/index",
//这里只是重定向浏览器地址,但是渲染还是在父级,
// 好处:就是可以打破不用和父同名默认是首页的规则
children: [{
path: "/index",
name: "index",
meta: {
title: "首页"
},
component: () => import('@/views/index')
},
{
path: "/user",
name: "user",
meta: {
title: "用户管理",
isAuth: true
},
component: () => import('@/views/user/index')
},
{
path: "/course",
name: "course",
meta: {
title: "课程管理"
},
component: () => import('@/views/course/index')
},
{
path: "/order",
name: "order",
meta: {
title: "订单管理"
},
component: () => import('@/views/order/index')
}
]
},
{
path: "/login",
name: "login",
component: () => import('@/views/login')
},
{
path: "/toLogin",
redirect: "/login"
},
{
path: "/error",
name: "error",
component: () => import('@/views/error')
}
]
const router = new VueRouter({
routes
})
// 前置通知(上面的路由配置可以根据自己的业务需求进行替换,重点在这)
router.beforeEach((to, from, next) => {
if (to.matched.length == 0) {
return next({
path: "/error"
})
} else if (to.path == "/login") {
// 1: 排除不需要拦截的授权的页面
return next();
} else {
//1: 如果登录成功,直接访问成功
// 在js中判断字符串是否为空的话可以直接这样判断(sessionStorage.token是后台返回的token被存在了sessionStorage中,sessionStorage.token这个可以直接获取)
if (sessionStorage.token) {
return next();
} else {
// 2: 如果用户访问的受保护的资源,且没有登录,则跳转到登录页面
// 举个场景:在操作系统,但是突然要吃饭了,过了30分钟以后继续来访问系统。因为token有时间限制。这个肯定会转发登录去、
// 为了良好的体验
// 将当前路由的完整的地址做为参数传递给Login.vue的组件,以便登录成功以后继续回到该位置
return next({
path: "/login",
query: {
back: to.fullPath
}
})
}
}
next();
})
// 后置通知
router.afterEach(to => {
document.title = to.meta.title;
})
export default router
封装axios请求
// 1: 导入异步处理
import axios from "axios";
// 2: 创建axios异步实列对象
const request = axios.create({
//`baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
baseURL: "根目录",// 设置后每次都请求都会在前面加上这个url 比如可以写http://127.0.0.1:8081/api/
// 请求服务器最大时长,如果请求超过这个时间直接终止
timeout: 10000
// 设置请求头信息
//headers: {'X-Custom-Header': 'foobar'} // 不建议:因为太死了
});
// 添加请求拦截器
// 在执行axios.get/post 在来进行处理加工
request.interceptors.request.use(function (config) {
// 获取toekn
var token = sessionStorage.getItem("token");
if (token) {
config.headers['Authorization'] = 'Bearer ' + token // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
// 这里处理post逻辑 这个post默认的是application/json 所以后台必须使用@requestBody注解进行接受
if (config.method === 'post' || config.method === 'put') {
if (!config.data) {
config.data = {};
}
}
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
request.interceptors.response.use(function (response) {
if (response.data.status === 500) {
console.log("1")
} else if (response.data.status === 600) {
console.log("2")
} else {
// 对响应数据做点什么
return response.data;
}
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
result += subPart + encodeURIComponent(value[key]) + "&";
}
}
} else {
result += part + encodeURIComponent(value) + "&";
}
}
}
return result
}
// 3: 导出
export default request;

被折叠的 条评论
为什么被折叠?



