实现原理:

哪些路由需要验证需要在路由文件router/index.js中指定:

    {
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/chart',
component: Chart,
name: 'Chart',
iconCls: 'el-icon-s-flag',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
}

用户有没有登录需要给其指定状态,当用户登录了,我们用localStorage在Login.vue文件中为其状态指定为1:

            that.$axios({
method: 'post',
url: 'http://localhost:9999/article/check_login_status/',
data: param
})
.then((res) => {
if(res.data.ret){
localStorage.setItem("islogin", 1); // 指定登录状态
that.$router.push({path: "/table"});
}else{
that.$message('用户名或密码错误!');
return false;
}
})
.catch((e) => {
console.log(err);
});

退出时需要在Home.vue中为其指定状态为0:

localStorage.setItem("islogin", 0);

路由拦截需要用到导航守卫,关键代码如下:

router.beforeEach((to, from, next) => {
let islogin = localStorage.getItem("islogin");
islogin = Boolean(Number(islogin)); if(to.path == "/login"){
if(islogin){
next("/table");
}else{
next();
}
}else{
// requireAuth:可以在路由元信息指定哪些页面需要登录权限
if(to.meta.requireAuth && islogin) {
next();
}else{
next("/login");
}
}
})

全部代码:

router/index.js:

import Vue from 'vue'
import Router from 'vue-router'
const Home = () => import('@/components/HelloWorld')
const Badge = () => import('@/components/Badge')
const Progress = () => import('@/components/Progress')
const Table = () => import('@/components/Table')
const Tag = () => import('@/components/Tag')
const Chart = () => import('@/components/Chart')
const NotFound = () => import('@/components/NotFound')
const Login = () => import('@/components/Login')
const Tabs = () => import('@/components/Tabs')
const Rate = () => import('@/components/Rate')
const Form = () => import('@/components/Form') Vue.use(Router) let router = new Router({
routes: [
{
path: '/',
component: Home,
name: '导航一',
iconCls: 'el-icon-s-flag',
leaf: false,
children: [
{
path: '/tabs',
component: Tabs,
name: 'Tabs',
iconCls: 'el-icon-star-on',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
},
{
path: '/rate',
component: Rate,
name: 'Rate',
iconCls: 'el-icon-star-on',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/badge',
component: Badge,
name: 'Badge',
iconCls: 'el-icon-s-help',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/table',
component: Table,
name: 'Table',
iconCls: 'el-icon-upload',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/tag',
component: Tag,
name: 'Tag',
iconCls: 'el-icon-s-cooperation',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/progress',
component: Progress,
name: 'Progress',
iconCls: 'el-icon-s-order',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/chart',
component: Chart,
name: 'Chart',
iconCls: 'el-icon-s-flag',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/',
component: Home,
name: 'Home',
iconCls: 'fa fa-address-card',
leaf: true,//只有一个节点
children: [
{
path: '/form',
component: Form,
name: 'Form',
iconCls: 'el-icon-s-flag',
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
}
]
},
{
path: '/login',
name: 'Login',
component: Login,
hidden: true,
meta: { // 在路由配置中加入meta:{requireAuth: true}
requireAuth: true
}
},
{
path: '*',
hidden: true,
redirect: { path: '/404' }
},
{
path: '/404',
hidden: true,
name: '',
component: NotFound
}
]
}) export default router router.beforeEach((to, from, next) => {
let islogin = localStorage.getItem("islogin");
islogin = Boolean(Number(islogin)); if(to.path == "/login"){
if(islogin){
next("/table");
}else{
next();
}
}else{
// requireAuth:可以在路由元信息指定哪些页面需要登录权限
if(to.meta.requireAuth && islogin) {
next();
}else{
next("/login");
}
}
})

Login.vue:

<template>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm login-container">
<el-form-item label="用户名" prop="username">
<el-input v-model="ruleForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</template> <script>
export default {
data() {
return {
ruleForm: {
username: '',
password: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 8, message: '长度在 3 到 8 个字符', trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
let that = this; let param = new URLSearchParams();
param.append('username', that.ruleForm.username);
param.append('password', that.ruleForm.password); this.$refs[formName].validate((valid) => {
if (valid) {
that.$axios({
method: 'post',
url: 'http://localhost:9999/article/check_login_status/',
data: param
})
.then((res) => {
if(res.data.ret){
localStorage.setItem("islogin", 1);
console.log(localStorage.getItem("islogin"));
that.$router.push({path: "/table"});
}else{
that.$message('用户名或密码错误!');
return false;
}
})
.catch((e) => {
console.log(err);
});
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script> <style scoped>
.login-container {
/*box-shadow: 0 0px 8px 0 rgba(0, 0, 0, 0.06), 0 1px 0px 0 rgba(0, 0, 0, 0.02);*/
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
background-clip: padding-box;
margin: 180px auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
.title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
.remember {
margin: 0px 0px 35px 0px;
}
} </style>

Home.vue:

<template>
<div id="app">
<el-container>
<el-header>Header <el-button @click="loginOut">退出</el-button></el-header>
<el-container>
<el-aside width="200px">
<el-row class="tac">
<el-col :span="24">
<el-menu
:default-active="$route.path"
router unique-opened
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"> <template v-for="(item, index) in $router.options.routes" v-if="!item.hidden">
<!--二级菜单-->
<template v-if="!item.leaf" >
<el-submenu :index="index+''">
<template slot="title">
<i :class="item.iconCls"></i>
<span>{{item.name}}</span>
</template>
<el-menu-item-group>
<el-menu-item :index="child.path" :key="index" v-for="(child, index) in item.children">
{{child.name}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</template> <!--一级菜单-->
<template v-else>
<el-menu-item :index="child.path" :key="child.path" v-for="(child, index) in item.children">
<i :class="child.iconCls"></i>
<span slot="title">{{child.name}}</span>
</el-menu-item>
</template>
<!-- <subMenu v-else :data="item" :key="key"></subMenu> -->
</template> </el-menu>
</el-col>
</el-row>
</el-aside> <el-main>
<el-row>
<el-col :span="24">
<div class="grid-content" style="padding: 20px;">
<router-view/>
</div>
</el-col>
</el-row> </el-main>
</el-container>
</el-container>
</div>
</template> <script>
import {mapState, mapGetters, mapActions} from 'vuex' export default {
name: 'App',
methods: {
handleOpen(key, keyPath) {
//console.log(key, keyPath);
},
handleClose(key, keyPath) {
//console.log(key, keyPath);
},
...mapActions('People', ['asyncSetName']),
asyncSetAge(){
this.$store.dispatch("People/asyncSetAge", 1);
},
asyncSetAddress(){
this.$store.dispatch("People/asyncSetAddress", "中国湖南长沙");
},
asyncSetJob(){
this.$store.dispatch("People/asyncSetJob", "P9");
},
loginOut(){
localStorage.setItem("islogin", 0);
this.$router.push("/login");
}
},
computed: {
...mapState('People', ['name', 'age', 'address', 'job']),
...mapState('Product', {
productName: 'name',
count: 'count',
price(state){return state.price},
mount: state => state.mount
}),
}
}
</script> <style>
body{
margin: 0;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
} .el-row {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.el-col {
border-radius: 4px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.row-bg {
padding: 10px 0;
background-color: #f9fafc;
} .el-header, .el-footer {
background-color: #235d8b;
color: #ffffff;
text-align: left;
line-height: 60px;
position: absolute;
top: 0;
left: 0;
height: 60px;
width: 100%;
z-index: 100;
} .el-aside {
background-color: #4175a4;
color: #ffffff;
text-align: left;
height: 100%;
z-index: 10;
position: absolute;
left: 0;
top: 0;
padding-top: 80px;
} .el-main {
background-color: #FFFFFF;
color: #333;
text-align: left;
height: 100%;
position: absolute;
left: 0;
top: 0;
padding-top: 80px;
padding-left: 210px;
width: 100%;
} body > .el-container {
margin-bottom: 40px;
} .el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
} .el-container:nth-child(7) .el-aside {
line-height: 320px;
}
.el-menu-vertical-demo{
background:#4175a4;
}
</style>

django代码:views.py

@csrf_exempt
def check_login_status(request):
return_dict = {"ret": False} if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'admin' and password == '123456':
return_dict['ret'] = True return HttpResponse(json.dumps(return_dict), content_type="application/json")

vue路由登录拦截(vue router登录权限控制)的更多相关文章

  1. vue路由钩子拦截器beforeEach和afterEach及页面路由变化路由监听

    在路由跳转的时候,我们需要一些权限判断或者其他操作.这个时候就需要使用路由的钩子函数. 定义:路由钩子主要是给使用者在路由发生变化时进行一些特殊的处理而定义的函数. 总体来讲vue里面提供了三大类钩子 ...

  2. vue中如何实现后台管理系统的权限控制

    vuejs单页应用的权限管理实践 一.前言 在广告机项目中,角色的权限管理是卡了挺久的一个难点.首先我们确定的权限控制分为两大部分,其中根据粒的大小分的更细: 接口访问的权限控制 页面的权限控制 菜单 ...

  3. 详解基于vue,vue-router, vuex以及addRoutes进行权限控制

    基于vuex, vue-router,vuex的权限控制教程,完整代码地址见https://github.com/linrunzheng/vue-permission-control 接下来让我们模拟 ...

  4. ASP.NET Core利用拦截器 IActionFilter实现权限控制

    “麦荻网教系统”采用了前后端代码分离的架构,即“Miidy.Cloud.Console”站与“Miidy.Cloud.Manage”站(两个前端站)同时通过web api的方式调用“Miidy.Clo ...

  5. Springboot + Vue + shiro 实现前后端分离、权限控制

    本文总结自实习中对项目对重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelA ...

  6. Spring Boot + Vue + Shiro 实现前后端分离、权限控制

    本文总结自实习中对项目的重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelA ...

  7. vue路由配置,vue子路由配置

    上一篇关于vue环境配置已经写好了!按照操作就行了! 现在一个项目已经部署完成,接下来我们从路由开始! 还记得在初始化项目的时候,有提示是否需要安装vue-router,对没错,vue中路由全靠它! ...

  8. vue路由嵌套,vue動態路由

    https://www.cnblogs.com/null11/p/7486735.html https://www.cnblogs.com/goloving/p/9271501.html https: ...

  9. vue路由守卫用于登录验证权限拦截

    vue路由守卫用于登录验证权限拦截 vue路由守卫 - 全局(router.beforeEach((to, from, next) =>来判断登录和路由跳转状态) 主要方法: to:进入到哪个路 ...

随机推荐

  1. VC++ 窗口透明化及透明窗口上绘画、截图、轨迹

    源文件:https://files.cnblogs.com/files/MrFengD/Temp.rar

  2. 3d长方体

    html <div class="main"> <div class="a1">1</div> <div class= ...

  3. Android MediaPlayer 在 STREAM_ALARM 中播放媒体

    最近因为公司需求,要实现后台播放音频,同时广告机中的视频因为客户需求调至静音,不能通过修改系统的媒体音量来让音频发声. private MediaPlayer mediaPlayer; private ...

  4. JSONObject 的使用

    1. 导入依赖 这里以 20180813 的 json 版本为例 <dependency> <groupId>org.json</groupId> <arti ...

  5. 深入理解hadoop之排序

    MapReduce的排序是默认按照Key排序的,也就是说输出的时候,key会按照大小或字典顺序来输出,比如一个简单的wordcount,出现的结果也会是左侧的字母按照字典顺序排列.下面我们主要聊聊面试 ...

  6. HTML的学习2(代码)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. Anaconda--机器学习环境搭建

    使用Anaconda为机器学习和深度学习设置Python环境 一.安装Anaconda,并更新到最新版本 1.Anaconda 安装: 官方网站下载地址 https://www.anaconda.co ...

  8. vue 编辑

    点击文字修改 <div class="baseInfo"> <p class="title">基本信息</p> <p ...

  9. jeesite表字段太多导致不能自动生成那张表的代码——————jetty 之 form too large | form too many keys 异常

    看了Jetty的源码才发现,jetty限制了Form提交数据的大小,该源码类来自jetty lib库下的jetty-server-7.6.16.v20140903.jar包下的 org.eclipse ...

  10. vue+ckEditor5

    1.安装依赖 "@ckeditor/ckeditor5-build-balloon": "^10.1.0", "@ckeditor/ckeditor5 ...