diff --git a/src/api/login.js b/src/api/login.js new file mode 100644 index 0000000..8dab90c --- /dev/null +++ b/src/api/login.js @@ -0,0 +1,24 @@ +import request from '@/utils/request'; + +export function loginOptions() { + return request({ + url: '/login-options', + method: 'get', + }) +} + +export function oidcAuth (data) { + return request({ + url: '/oidc/auth', + method: 'post', + data, + }) +} + +export function oidcQuery(params){ + return request({ + url: '/oidc/auth-query', + method: 'get', + params, + }) +} \ No newline at end of file diff --git a/src/store/user.js b/src/store/user.js index d1201d0..5d7933c 100644 --- a/src/store/user.js +++ b/src/store/user.js @@ -1,8 +1,9 @@ import { defineStore, acceptHMRUpdate } from 'pinia' import { current, login } from '@/api/user' -import { setToken, removeToken } from '@/utils/auth' +import { setToken, removeToken, setCode, removeCode } from '@/utils/auth' import { useRouteStore } from '@/store/router' import { useAppStore } from '@/store/app' +import { oidcAuth, oidcQuery } from '@/api/login'; export const useUserStore = defineStore({ id: 'user', @@ -16,34 +17,40 @@ export const useUserStore = defineStore({ }), actions: { - logout () { + logout() { removeToken() + removeCode() this.$patch({ name: '', role: {}, }) }, - async login (form) { + saveUserData(userData) { + // useAppStore().getAppConfig() + setToken(userData.token) + // + localStorage.setItem('user_info', JSON.stringify({ name: userData.username })) + this.$patch({ + ...userData, + }) + if (userData.route_names && userData.route_names.length) { + useRouteStore().addRoutes(userData.route_names) + } + }, + + async login(form) { const res = await login(form).catch(_ => false) if (res) { useAppStore().getAppConfig() const userData = res.data - setToken(userData.token) - // - localStorage.setItem('user_info', JSON.stringify({ name: userData.username })) - this.$patch({ - ...userData, - }) - if (userData.route_names && userData.route_names.length) { - useRouteStore().addRoutes(userData.route_names) - } + this.saveUserData(userData) return userData } else { return false } }, - async info () { + async info() { const res = await current().catch(_ => false) if (res) { useAppStore().getAppConfig() @@ -57,6 +64,41 @@ export const useUserStore = defineStore({ } return false }, + async oidc(provider, platform, browser) { + // oidc data need to be implement + const data = { + deviceInfo: { + name: navigator.userAgent, // 使用浏览器的 User-Agent 作为设备名 + os: platform, // 获取操作系统信息 + type: 'webadmin', // any vaule + }, + id: `${platform}-${browser}`, + op: provider, // 传入的 provider + uuid: crypto.randomUUID(), // 自动生成 UUID + }; + const res = await oidcAuth(data).catch(_ => false) + if (res) { + const { code, url } = res.data + setCode(code) + if (provider == 'webauth') { + window.open(url) + } else { + window.location.href = url + } + } + }, + async query(code) { + const params = { "code": code, "uuid": crypto.randomUUID(), "Id": "999" } + const res = await oidcQuery(params).catch(_ => false) + if (res) { + removeCode() + useAppStore().getAppConfig() + const userData = res.data + this.saveUserData(userData) + return userData + } + return false + } }, }) diff --git a/src/utils/auth.js b/src/utils/auth.js index 4266de0..82f25ee 100644 --- a/src/utils/auth.js +++ b/src/utils/auth.js @@ -1,4 +1,6 @@ const TokenKey = 'access_token' +const OidcCode = 'oidc_code' +const OidcCodeExpiry = 'oidc_code_expiry'; export function getToken () { return localStorage.getItem(TokenKey) @@ -11,3 +13,31 @@ export function setToken (token) { export function removeToken () { return localStorage.removeItem(TokenKey) } + +// 设置 code,并存储当前时间戳(单位:毫秒) +export function setCode(code) { + const now = Date.now(); // 当前时间戳(毫秒) + const expiry = now + 30 * 1000; // 30 秒后过期 + + localStorage.setItem(OidcCode, code); // 存储 code + localStorage.setItem(OidcCodeExpiry, expiry); // 存储过期时间戳 +} + +// 获取 code,如果已过期则删除并返回 null +export function getCode() { + const expiry = localStorage.getItem(OidcCodeExpiry); // 获取过期时间戳 + const now = Date.now(); // 当前时间戳 + + if (expiry && now > parseInt(expiry)) { + // 如果已过期,删除 code 和过期时间 + removeCode(); + return null; + } + return localStorage.getItem(OidcCode); // 返回 code(如果未过期) +} + +// 删除 code 和过期时间 +export function removeCode() { + localStorage.removeItem(OidcCode); + localStorage.removeItem(OidcCodeExpiry); +} \ No newline at end of file diff --git a/src/utils/i18n/zh_CN.json b/src/utils/i18n/zh_CN.json index 9870a53..0019fbb 100644 --- a/src/utils/i18n/zh_CN.json +++ b/src/utils/i18n/zh_CN.json @@ -427,5 +427,9 @@ }, "LastOnlineIp": { "One": "最后在线IP" + }, + "or login in with" : + { + "One": "或使用以下登陆" } } diff --git a/src/utils/request.js b/src/utils/request.js index f1215f1..3b4fb9a 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -55,6 +55,12 @@ service.interceptors.response.use( response => { const res = response.data + // for the endpoint /login-options + // I'm not sure if this is a good idea + if (Array.isArray(res)) { + return res; + } + // if the custom code is not 20000, it is judged as an error. if (res.code !== 0) { ElMessage({ diff --git a/src/views/login/login.vue b/src/views/login/login.vue index 6ada8d5..ec983c5 100644 --- a/src/views/login/login.vue +++ b/src/views/login/login.vue @@ -1,98 +1,252 @@ + \ No newline at end of file