feature: refresh token. if not logged in then refresh token; else redirect to login page.

This commit is contained in:
Cindy Chang
2024-06-28 12:10:19 +08:00
parent 9b2bab9124
commit a4aab21b98
5 changed files with 84 additions and 50 deletions

View File

@@ -1,7 +1,7 @@
import { createRouter, createWebHistory, } from "vue-router"; import { createRouter, createWebHistory, } from "vue-router";
import AuthContainer from '@/views/AuthContainer.vue'; import AuthContainer from '@/views/AuthContainer.vue';
import MainContainer from '@/views/MainContainer.vue'; import MainContainer from '@/views/MainContainer.vue';
import Login from '@/views/Login/index.vue'; import Login from '@/views/Login/Login.vue';
import Files from '@/views/Files/index.vue'; import Files from '@/views/Files/index.vue';
import Upload from '@/views/Upload/index.vue'; import Upload from '@/views/Upload/index.vue';
import Map from '@/views/Discover/Map/index.vue'; import Map from '@/views/Discover/Map/index.vue';

View File

@@ -1,7 +1,7 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import axios from 'axios'; import axios from 'axios';
import apiError from '@/module/apiError.js'; import apiError from '@/module/apiError.js';
import { deleteCookie, setCookie } from "../utils/cookieUtil"; import { deleteCookie, setCookie, getCookie } from "../utils/cookieUtil";
export default defineStore('loginStore', { export default defineStore('loginStore', {
// data, methods, computed // data, methods, computed
@@ -11,13 +11,13 @@ export default defineStore('loginStore', {
grant_type: 'password', // password | refresh_token grant_type: 'password', // password | refresh_token
username: '', username: '',
password: '', password: '',
refresh_token: '' refresh_token: undefined,
}, },
isInvalid: false, isInvalid: false,
userData: {}, userData: {},
isLoggedIn: false, isLoggedIn: false,
rememberedReturnToUrl: "", rememberedReturnToUrl: "",
// expired: new Date().setMonth(6), // 設定 Refresh Token 的到期日為半年後 expired: new Date().setMonth(6), // 設定 Refresh Token 的到期日為半年後
}), }),
actions: { actions: {
/** /**
@@ -35,10 +35,10 @@ export default defineStore('loginStore', {
try { try {
const response = await axios.post(api, this.auth, config); const response = await axios.post(api, this.auth, config);
const accessToken = response.data.access_token; const accessToken = response.data.access_token;
const refreshToken = response.data.refresh_token; const refresh_token = response.data.refresh_token;
// 將 token 儲存在 cookie // 將 token 儲存在 cookie
document.cookie = `luciaToken=${accessToken}`; document.cookie = `luciaToken=${accessToken}`;
// document.cookie = `luciaRefreshToken=${refreshToken};expires=${new Date(this.expired)};`; document.cookie = `luciaRefreshToken=${refresh_token};expires=${new Date(this.expired)};`;
this.isLoggedIn = true; this.isLoggedIn = true;
setCookie("isLuciaLoggedIn", "true"); setCookie("isLuciaLoggedIn", "true");
@@ -57,27 +57,31 @@ export default defineStore('loginStore', {
}; };
}, },
/** /**
* Refresh Token (暫時沒做) * Refresh Token
*/ */
async refreshTokenLogin() { async refreshToken() {
console.log('TODO:TODO:', this.auth);
const api = '/api/oauth/token'; const api = '/api/oauth/token';
const refreshToken = document.cookie.replace(/(?:(?:^|.*;\s*)luciaRefreshToken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
this.auth.grant_type = 'refresh_token'; this.auth.grant_type = 'refresh_token';
this.auth.refresh_token = refreshToken; this.auth.refresh_token = getCookie("luciaRefreshToken");
// try { try {
// const response = await axios.post(api, this.auth, config); const response = await axios.post(api, this.auth, config);
// const newAccessToken = response.data.access_token; console.log('response', response);
// const newRefreshToken = response.data.refresh_token; if(response.status === 200) {
const newAccessToken = response.data.access_token;
// document.cookie = `luciaToken=${newAccessToken}`; const newRefreshToken = response.data.refresh_token;
// document.cookie = `luciaRefreshToken=${newRefreshToken};expires=${this.expired}`;
document.cookie = `luciaToken=${newAccessToken}`;
// defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`; document.cookie = `luciaRefreshToken=${newRefreshToken};expires=${this.expired}`;
// } catch(error) {
// this.$router.push('/login'); defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
// } }
} catch(error) {
// 若refresh token 失敗則導向至登入頁面
this.$router.push('/login');
}
}, },
/** /**
* Logout, tooken expired * Logout, tooken expired

View File

@@ -1,29 +1,33 @@
export function getCookie(name) { export function getCookie(name) {
const nameEQ = name + "="; const nameEqual = name + "=";
const ca = document.cookie.split(';'); const cookieArr = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) { for (let i = 0; i < cookieArr.length; i++) {
let c = ca[i]; let c = cookieArr[i];
while (c.charAt(0) === ' ') { while (c.charAt(0) === ' ') {
c = c.substring(1, c.length); c = c.substring(1, c.length);
} }
if (c.indexOf(nameEQ) === 0) { if (c.indexOf(nameEqual) === 0) {
return c.substring(nameEQ.length, c.length); return c.substring(nameEqual.length, c.length);
} }
} }
return null; return null;
} }
export function setCookie(name, value, days=1) { export function setCookie(name, value, days=1) {
let expires = ""; let expires = "";
if (days) { if (days) {
const date = new Date(); const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString(); expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
} }
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
export function deleteCookie(name, path = '/') { export function setCookieWithoutExpiration(name, value) {
document.cookie = name + '=; Max-Age=-99999999; path=' + path; document.cookie = name + "=" + (value || "");
} }
export function deleteCookie(name, path = '/') {
document.cookie = name + '=; Max-Age=-99999999; path=' + path;
}

View File

@@ -33,9 +33,11 @@ export default {
const allMapDataStore = AllMapDataStore(); const allMapDataStore = AllMapDataStore();
const conformanceStore = ConformanceStore(); const conformanceStore = ConformanceStore();
const pageAdminStore = PageAdminStore(); const pageAdminStore = PageAdminStore();
const loginStore = LoginStore();
const { tempFilterId, createFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore); const { tempFilterId, createFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore);
const { conformanceLogTempCheckId, conformanceFilterTempCheckId } = storeToRefs(conformanceStore); const { conformanceLogTempCheckId, conformanceFilterTempCheckId } = storeToRefs(conformanceStore);
const router = useRouter(); const router = useRouter();
const { isLoggedIn, auth } = storeToRefs(loginStore);
const setHighlightedNavItemOnLanding = () => { const setHighlightedNavItemOnLanding = () => {
const currentPath = router.currentRoute.value.path; const currentPath = router.currentRoute.value.path;
@@ -72,6 +74,7 @@ export default {
]), ]),
...mapState(LoginStore, [ ...mapState(LoginStore, [
'isLoggedIn', 'isLoggedIn',
'auth',
]) ])
}, },
methods: { methods: {
@@ -81,23 +84,46 @@ export default {
'clearShouldKeepPreviousPageBoolean', 'clearShouldKeepPreviousPageBoolean',
'setActivePageComputedByRoute', 'setActivePageComputedByRoute',
],), ],),
...mapActions(LoginStore, [
'refreshToken',
],),
}, },
created() { created() {
// Save token in Headers. // Save token in Headers.
const token = document.cookie.replace(/(?:(?:^|.*;\s*)luciaToken\s*\=\s*([^;]*).*$)|^.*$/, "$1"); const token = document.cookie.replace(/(?:(?:^|.*;\s*)luciaToken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
this.$http.defaults.headers.common['Authorization'] = `Bearer ${token}`; this.$http.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}, },
beforeRouteEnter(to, from, next) { // 重新整理畫面以及第一次進入網頁時beforeRouteEnter這個hook會被執行然而beforeRouteUpdate不會被執行
// 重新整理畫面以及第一次進入網頁時beforeRouteEnter這個hook會被執行然而beforeRouteUpdate不會被執行 // PSEUDOCODE
if (!getCookie("isLuciaLoggedIn")) { // if (not logged in) {
next({ // if (has refresh token) {
path: '/login', // refresh_token();
query: { // if (refresh failed) {
'return-to': btoa(window.location.href), // go to log in();
} // } else {
}); // cookie add("refresh_token=" + refresh_token "; expire=****")
} else { // }
next(); // } else {
// go to log in();
// }
// }
beforeRouteEnter(to, from, next) {
const loginStore = LoginStore();
if (!loginStore.isLoggedIn) {
if (getCookie('luciaRefreshToken')) {
loginStore.refreshToken();
} else {
next({
path: '/login',
query: {
// 記憶未來登入後要進入的網址且記憶的時候要用base64編碼包裹住
'return-to': btoa(window.location.href),
}
});
}
} else {
next();
} }
}, },
// Remember, Swal modal handling is called before beforeRouteUpdate // Remember, Swal modal handling is called before beforeRouteUpdate