• <ol id="gebcs"></ol>
    <track id="gebcs"><i id="gebcs"></i></track>

    基于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");

    效果如下:


    黄片基地 <