基于vue导航守卫和veux的登陆及退出实例

时间:2021-08-23 11:29:14 类型:vue
字号:    

一. 安装vuex及永久化vuex)

     npm i vuex

     npm install --save vuex-persistedstate

     在 src 目录下 创建 "store" 文件夹, 并在文件夹下创建index.js文件, 代码如下:

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
Vue.use(Vuex); 
const state = {
		'token'    : ''
};
const mutations = {
		changeToken(state,params){
			state.token = params;
		}
		
};


const store = new Vuex.Store({
   plugins:[createPersistedState()],
   state : state, //状态管理
   mutations:mutations, //修改state
   modules:{} //模块
});
 
export default store;

//main.js文件引入
import store from './store';

二. 安装Element组件 及axios组件

     npm i element-ui -S

   npm install axios --save

     main.js文件引入

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

import axios from 'axios';

axios.defaults.baseURL='

new Vue({
  router,
  store, //注入,组件中可以使用 this.$store 获取
  render: h => h(App)
}).$mount('#app');

三. views下创建login.vue组件, 代码如下:

<template>
		<div>
			<Header></Header>
			<el-form ref="form"  label-width="80px" class="form">
			  <el-form-item label="用户名">
			    <el-input v-model="form.username" clearable></el-input>
			  </el-form-item>
			  <el-form-item label="密码" >
			    <el-input v-model="form.userpwd" show-password></el-input>
			  </el-form-item>
			 
			  <el-form-item>
			    <el-button type="primary" @click="login">登陆</el-button>
			    <el-button>取消</el-button>
			  </el-form-item>
			</el-form>
		</div>
</template>

<script>
	console.log(localStorage.getItem('preRoute'));
	import Header from "@/components/Header"
	export default{
		data() {
		      return {
		        form: {
		          username: '',
				  userpwd : ''
		        },
		      }
		},
		components:{
			Header
		},
		methods:{
			login(){
				if(this.form.username == ''){
					this.$message({ message: '用户名不能为空', type: 'warning',offset:200});
					return false;
				}
				if(this.form.userpwd == ''){
					this.$message({ message: '用户密码不能为空', type: 'warning',offset:200});
					return false;
				}
				// console.log(this.form);
				// return ;
				this.axios.post("loginCheck",{params:this.form}).then(res=>{
					let _this =  this;
					if(res.data.code == 1){
						this.$store.commit("changeToken",res.data.token);
						
						
						this.$message({
						          message: '登陆成功',
						          type: 'success',
								  offset:200,
								  onClose:()=>{
									// Object.keys(_this.data).forEach(key=>{_this.data[key]=''})
								  }
						        });
						const curr = localStorage.getItem('preRoute')
						if (curr == null) {
							this.$router.push({ path: "/" });
						} else {
							this.$router.push({ path: curr });//跳转到来源页面
						}
					}
					else{
						this.$message({
						          message: '账号密码不正确',
						          type: 'warning',
								  offset:200
						        });
					}
					
				})
			}
		}
	}
</script>

<style>
	.form{
		width:300px;
		margin: 20px auto;
	}
</style>

四. 创建安全退出文件Exit.vue

<template>
		<div>
			<Header></Header>
		</div>
</template>

<script>
	import Header from "@/components/Header"
	export default{
			components:{
				Header
			},
			mounted(){
				this.$store.commit("changeToken","");
				this.$message({
				  message: '安全退出',
				  type: 'success',
				  offset:200,
				  onClose:()=>{
				          this.$router.push({ path: "/"});                         //此处写提示关闭后需要执行的函数
				   }
				});
				
			}
		}
</script>

五, 配置路由及导航守卫

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Store from '../store'
import axios from 'axios';

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
	 meta: {login_require:true}
  },
  {
    path: '/contact',
    name: 'Cantact',
    component:()=>import('../views/Contact.vue'),
	 meta: {login_require:true}
  },
  {
	  path:'/message',
	  name:'Message',
	  component:()=>import('../views/Message.vue'),
	   meta: {login_require:true}
  },
  {
	  path:'/about',
	  name:'About',
	  component:()=>import('../views/About.vue'),
	   meta: {login_require:true}
  },
  {
	  path:'/news',
	  name:'News',
	  component:()=>import("../views/News.vue"),
	   meta: {login_require:true}
  },
  {
	  path:'/newsdetail',
	  name:'Newsdetail',
	  component:()=>import("../views/Newsdetail.vue"),
	   meta: {login_require:true}
  },
  {
	  path:'/vuexx',
	  name:'Vuexx',
	  component:() => import('../views/Vuexx.vue'),
	   meta: {login_require:true}
	 
  },
  {
  	  path:'/vuea',
  	  name:'Vuea',
  	  component:() => import('../views/Vuea.vue'),
	   meta: {login_require:true}
  	 
  },
  {
	  path:'/eleform',
	  name:'Eleform',
	  component:()=> import('../views/Eleform.vue'),
	   meta: {login_require:true}
  },
  {
	  path:'/mysecret',
	  name:'Mysecret',
	  component:()=> import('../views/mysecret.vue'),
	  meta: {login_require:false}
  },
  {
	  path:'/login',
	  name:"Login",
	  component:()=> import('../views/login.vue'),
	  meta: {login_require:true}
  },
  {
	  path:'/exit',
	  name:"Exit",
	  component:()=> import('../views/Exit.vue'),
	   meta: {login_require:true}
  }
]

const router = new VueRouter({
  routes
})
router.beforeEach((to,from,next)=>{
	let token = Store.state.token;
	if ((to.matched.some(function (item) {
			return item.meta.login_require
	  }))) {
	    next();
	  } 
	else {
		if(token == ""){
			//没有得到token, 所以去登陆
			localStorage.setItem("preRoute", router.currentRoute.fullPath); //保存当前路径 
			if(to.path == "/login" || to.path == "/exit"){
				next();
			}
			else{
				next("/login");
			}
		}
		else{
			//有了token值, 然后判断是否是正确的, 有没有过期等
			axios({
			    method: 'get',
			    url: "http://ggqvue.cn/vue/jwtTokenVerify",
			    headers: { 'Authorization': token }
				//params:{token:token}
			  }).then(res => {
			     if(res.data.code == 2){ //验证有问题
				    // console.log("验证不通过");
					 localStorage.setItem("preRoute", router.currentRoute.fullPath)
					 if(to.path == "/login" || to.path == "/exit"){
					 	next();
					 }
					 else{
					 	next("/login");
					 }
				 }
				 else{
					// console.log("验证通过");
					 next();
				 }
			  }).catch(e => {
			  	
			  })
			  
			
		}
	}
    
 })
export default router

   六. 后台登陆及token验证

  public function loginCheck(){
        $post = $this->request->post("params");
        // halt($post);
        //模拟比较, 实际应用中通常 从数据库中查询比对
        if($post["username"] == "admin" && $post["userpwd"] == "123456"){
             $payload=[
                'iss'=>'庄子',
                'iat'=>time(),
                'exp'=>time()+7200,
                'nbf'=>time(),
                'sub'=>'用户登陆操作',
                'jti'=>md5(uniqid('JWT').time()),
                "username"=>$post["username"]
            ];
            $token=\Jwt::getToken($payload);
            return json(["code"=>1, "mes"=>"登陆成功","token"=>$token]);
        }
        else{
             return json(["code"=>2, "mes"=>"登陆失败"]);
        }
    }

     public function jwtTokenVerify(){

            $token = $this->request->header("Authorization");
           //对token进行验证签名
            $result = \Jwt::verifyToken($token);
            if($result["code"] == 1){
                return json(["code"=>1,"mes"=>"success", "username"=>$result["payload"]["username"]]);
            }
            else{
                return json(["code"=>2,"mes"=>"fail"]);
            }
    }

注意: php端解决跨域操作的方法,在入口文件中加入以下内容:

header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:GET, POST, OPTIONS, DELETE");
header("Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Accept-Language, Origin, Accept-Encoding,Authorization");

效果如下:


<