登錄流程

首先說一下現在項目搭建的程度;

vue-cli 創建的項目

引入了 iview 組件庫,安裝好了 less,安裝了 vue-router 路由;

配置好了跳轉到後臺和登錄頁面的路由;

使用 iview做好了登錄頁面和後臺頁面的框架,如圖:

在這裏插入圖片描述
在這裏插入圖片描述

後臺是需要登錄之後才能訪問的,所以要對訪問進行攔截;

1. 標識一下需要攔截的頁面

一個網站有很多頁面,一些是需要登錄過後才能訪問的,一些是不用登錄也能訪問的;
所以我們要在路由中對需要登錄才能訪問的頁面進行一下標識,以區分這兩者;

標識 meta

// meta 字段中 auth_login 爲 true 的需要進行登錄攔截檢測;
{
    path: '/admin',
    component: Admin,
    meta: {
        auth_login: true
    },
    children: [
        {
            path: 'user',
            component: adminUser,
            meta: {
                auth_login: true
            },
        },
        {
            path: 'role',
            component: adminRole,
            meta: {
                auth_login: true
            },
        }
    ]
},

2. 路由攔截器

路由守衛也就是路由攔截器,通過路由攔截器在每一次路由跳轉的時候都做一下判斷,是否需要驗證登錄;

後續再判斷是否登錄成功,這裏先用 true代替;

const router = new vueRouter({...});

// 前置守衛--在進入新的路由前被攔截  路由攔截器
router.beforeEach((to, from, next)=>{
    /**
     * 1. to   到哪裏去(路由對象)
     * 2. from 從哪裏來(路由對象)
     * 3. next 是否允許通行(函數)
     * 
     * 查看 to中有沒有需要攔截的標識,判斷是否攔截
     * 不需要攔截的話直接 next() 通行;
     * 需要攔截的話,判斷是否登錄,如果登錄了則通行,沒登錄則攔截;
     */

    // 是否需要攔截
    if(to.meta.auth_login){
        // 需要攔截 -- 判斷是否登錄
        if(true){
            next();
        }else{
            next({path: '/login'})
        }
    }else{
        // 不需要攔截 -- 通行
        next();
    }
})

3. 請求

有些時候 前端頁面和服務接口不在同一個服務器,如果通過 ajax 請求的話是會碰到跨域問題的;
而在 webpack 服務器中有一個 代理轉發請求 的功能可以解決這個問題;就是我們請求自己的服務器,由服務器去請求數據,因爲跨域是瀏覽器限制的,在 nodejs是沒有限制的;

如:
前端地址:
http://localhost:8080/login
服務器地址:
http://console.ranyunlong.com:8080/renren-fast/swagger/

大體流程就是:
我們從瀏覽器請求開發服務器 (webpack-dev-server),開發服務器請求真實的服務器,真實的服務器把結果返回給開發服務器,開發服務器再返回給瀏覽器;
在這裏插入圖片描述

在開發服務器中配置規則:
vue-cli 3.0 中配置 webpack的方式:

https://cli.vuejs.org/zh/guide/webpack.html#簡單的配置方式

1)新建文件 vue.config.js

2)進行配置

https://www.webpackjs.com/configuration/dev-server/#devserver-proxy

【vue.config.js】

module.exports = {
    devServer: {
        proxy: {
            "/api": {
                // 轉發的目標地址
                target: "http://console.ranyunlong.com:8080",
                // 路徑重寫
                pathRewrite: {
                    "^/api": "/renren-fast"
                }
            }
        }
    }
}

講解:

真實路徑:
http://console.ranyunlong.com:8080/renren-fast/sys/login

但是如果我們訪問這個路徑就跨域了,所以我們要訪問我們的開發服務器:
http://localhost:8080/api/sys/login

經過如上規則配置就相當於訪問了真實路徑;

當我們訪問的路徑有 /api時,就匹配了 devServer.proxy 的規則,進入了我們寫的這條規則;

就會把我們的 http://localhost:8080 替換成 target的目標地址http://console.ranyunlong.com:8080
變成:
http://console.ranyunlong.com:8080/api/sys/login

再經過路徑重寫,將 /api替換成 /renren-fast
所以訪問到的路徑就是:
http://console.ranyunlong.com:8080/renren-fast/sys/login

3)測試配置是否生效

重啓服務器

訪問路徑:http://localhost:8080/api/captcha.jpg

返回:
{"msg":"uuid不能爲空","code":500}

和訪問真實的服務器返回的數據是相同的,配置成功;

4. 驗證碼

因爲已經做了代理了,所以可以直接訪問到 服務器的數據,驗證碼是通過 get 方式請求的,這裏直接寫就好了

<img src="/api/captcha.jpg?uuid=0101010" alt="">

但是這個的這個 uuid 只能用一次,這個問題可以通過模塊 uuid來解決;

https://www.npmjs.com/package/uuid

# 安裝
npm i uuid
// 導入
// uuid()會生成一個字符串
import uuid from 'uuid'

// 計算屬性拼接成驗證碼路徑;
// 沒有在計算屬性直接使用 uuid() 生成路徑是因爲後面要點擊驗證碼換一張驗證碼,計算屬性的值沒法設置,寫到 data方便後續更新;
export default {
	data() {
		return{
			uid: uuid()
		}
	},
	computed: {
		codeUrl(){
			return '/api/captcha.jpg?uuid=' + this.uid;
		}
	}
}
<!--綁定 計算屬性-->
<img :src="codeUrl" alt="">

點擊驗證碼,生成新的驗證碼

<img @click="newCodeUrl()" :src="codeUrl" alt="">
methods:{
    newCodeUrl(){
        this.uid = uuid();
    }
},
computed: {
    codeUrl(){
        return '/api/captcha.jpg?uuid=' + this.uid;
    }
},
data() {
	return{
		uid: uuid()
	}
},

5. 驗證表單數據

步驟見博客:

https://blog.csdn.net/qq_39125684/article/details/91125528

6. 表單提交

表單提交,是點擊登陸按鈕,然後檢測表單數據,檢測通過之後,進行 ajax 提交;

登錄按鈕

<Button @click="loginFn()" long>login</Button>

登錄按鈕 點擊事件

loginFn(){
    // this.$refs['loginForm']   表單對象

    this.$refs['loginForm'].validate((val)=>{
        /**
         * val  true:  效驗成功
         *      false: 效驗失敗
         */
 		
    });
}

axios
在這裏,我們提交沒有使用 ajax 而是使用了 axios 模塊;
文檔:https://www.kancloud.cn/yunye/axios/234845

1)安裝 axios

npm install axios

2)新建文件夾 src/api/

3)新建文件 src/api/http.js

在這裏使用自定義配置新建一個 axios 實例

// 導入 axios模塊
import axios from 'axios'

// 創建一個請求模板    新建一個axios 實例
const http = axios.create({
    // 設置基礎路徑
    baseURL: '/api',
})

// 攔截請求的 每次請求都會經過這個方法
http.interceptors.request.use((config) => {
    console.log(config);

    // 可以在這裏處理所有的 請求錯誤
    return config; 
})

// 攔截響應的 每次收到響應都會經過這個方法
http.interceptors.response.use((response)=>{
    console.log(response);

    // 可以在這裏處理所有的 響應錯誤
    return response;
})

// 暴露出去
export default http;

4) 登錄接口 src/api/login.js

導入新建的 axios 實例,然後執行 post 請求;

/**
 * 登錄接口
 */
 
import http from "./http";

function login(data){
    return http.post('/sys/login', data);
}


export default login;

5)在頁面中調用這個登錄接口,傳入數據

<Button @click="loginFn()" long>login</Button>
import login from  '../api/login'
_________

data(){
	return {
		uid: uuid(),
        userInfo: {
            username: '',
            password: '',
            captcha: ''
        },
	}
},
methods:{
    loginFn(){
        // this.$refs['loginForm']   表單對象

        this.$refs['loginForm'].validate((val)=>{
            /**
             * val  true:  效驗成功
             *      false: 效驗失敗
             */
            if(val) {
                login({
                    ...this.userInfo,
                    uuid: this.uid
                })
            }
        });
    }
},

6)通過響應消息判斷請求是否成功

請求成功:
存儲成功憑據:localStorage
跳轉到後臺頁面: this.$router.push('/admin')

請求失敗:
彈窗提示:iview 的全局提示
刷新驗證碼:this.uid = uuid();

loginFn(){
    // this.$refs['loginForm']   表單對象

    this.$refs['loginForm'].validate((val)=>{
        /**
         * val  true:  效驗成功
         *      false: 效驗失敗
         */
        if(val) {
            login({
                ...this.userInfo,
                uuid: this.uid
            }).then((response)=>{
                // response 響應過來的信息
                // response.data.code === 0  請求成功
                const {code, msg, token} = response.data;
                if(code === 0) {
                    // 請求成功,存儲成功信息
                    localStorage.setItem('token', token)
                    
                    // 路由跳轉
                    this.$router.push('/admin');
                }else {
                    // iview 的全局提示
                    this.$Message.error('登陸失敗:' + msg);
                    // 刷新驗證碼
                    this.uid = uuid();
                }
            })
        }
    });
}

在路由攔截器中,判斷是否有登陸憑證,有的話通行;
const loginResult = localStorage.getItem('token');

// 前置守衛--在進入新的路由前被攔截  路由攔截器
router.beforeEach((to, from, next)=>{
    /**
     * 1. to   到哪裏去(路由對象)
     * 2. from 從哪裏來(路由對象)
     * 3. next 是否允許通行(函數)
     * 
     * 查看 to中有沒有需要攔截的標識,判斷是否攔截
     * 不需要攔截的話直接 next() 通行;
     * 需要攔截的話,判斷是否登錄,如果登錄了則通行,沒登錄則攔截;
     */

    // 是否需要攔截
    if(to.meta.auth_login){
        // 需要攔截 -- 判斷是否登錄
        const loginResult = localStorage.getItem('token');
        if(loginResult){
            next();
        }else{
            next({path: '/login'})
        }
    }else{
        // 不需要攔截 -- 通行
        next();
    }
})

至此:登陸成功

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章