Переглянути джерело

加入子程序链接、跨域Cookie逻辑、重定义链接跳转

liyanbo 7 годин тому
батько
коміт
23cac176d1

+ 47 - 0
public/sub-jump.html

@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title>跳转校验中</title>
+</head>
+<body>
+加载中,正在校验登录状态...
+<script>
+    function getParam(name) {
+        const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
+        const r = window.location.search.substr(1).match(reg);
+        return r ? decodeURIComponent(r[2]) : null;
+    }
+    const targetUrl = getParam("target");
+    // 正确定义变量 localToken
+    const localToken = localStorage.getItem("token");
+    const loginFlag = localStorage.getItem('isLoggedIn');
+
+    console.log("localToken:", loginFlag, localToken);
+    // 第一层:本地缓存拦截
+    if (!localToken || loginFlag !== 'true') {
+        location.href = "https://learn-ai.com.cn/login?callback=" + encodeURIComponent(location.href);
+    }else {
+        location.href = targetUrl;
+    }
+
+    console.log("localToken:", loginFlag, localToken);
+    // 第二层携带Cookie校验后端token黑名单
+    // fetch(`/api/auth/token_check?token=${localToken}`, {
+    //     credentials: 'include'
+    // })
+    //     .then(res => {
+    //
+    //         console.log("res:", res);
+    //         if (res.ok) {
+    //             location.href = targetUrl;
+    //         } else {
+    //             location.href = "https://learn-ai.com.cn/login?callback=" + encodeURIComponent(location.href);
+    //         }
+    //     })
+    //     .catch(() => {
+    //         location.href = "https://learn-ai.com.cn/login?callback=" + encodeURIComponent(location.href);
+    //     })
+</script>
+</body>
+</html>

+ 3 - 3
src/api/login/login.js

@@ -23,9 +23,9 @@ export function getTenantIdByName (name){
 // 退出登录
 export function logout (data){
     return axios({
-        url: "system/auth/logout",
+        url: "bjdxWeb/web/logout",
         method: 'post',
-        data
+        data,
     })
 }
 
@@ -57,4 +57,4 @@ export function registerSignUp(headers,data){
         data: data,
         headers: headers,
     })
-}
+}

+ 5 - 0
src/components/user/UserInfoPopover.vue

@@ -44,6 +44,11 @@
               <span v-else>{{userInfo.roleRouteSet.includes(ROLE_KEY.AI_POETRY) ? '已开通' : '未开通'}}</span>
             </div>
           </div>
+
+
+          <a href="/sub-jump.html?target=https://entool.learn-ai.com.cn" rel="noopener noreferrer">
+            <button>英语探险家</button>
+          </a>
         </div>
 
         <!-- 激活码 -->

+ 10 - 1
src/router/index.js

@@ -12,6 +12,10 @@ const routes = [
     meta: { defaultQuery: { loginPath: '/parent-mobile-course' } },
     component: () => import('../views/Login-Mobile.vue')
   },
+  {
+    path: '/sub-jump',
+    component: () => import('../../public/sub-jump.html')
+  },
 
   // 免登录
   { path: '/quick-login', component: () => import('../views/QuickLogin.vue') },
@@ -291,13 +295,15 @@ router.beforeEach(async (to, from, next) => {
     '/reg',
     '/login-mobile',
     '/quick-login',
-    '/promotion-login'].includes(to.path)) {
+    '/promotion-login',
+    '/login'].includes(to.path)) {
     next()
     return
   }
 
   // 检查登录状态
   const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true'
+
   // 允许未登录用户访问的页面列表
   const allowedPages = Object.keys(loginToHomeMap)
 
@@ -305,6 +311,9 @@ router.beforeEach(async (to, from, next) => {
   if (!isLoggedIn && !allowedPages.includes(to.path)) {
     next('/login')
     return
+  }else if(to.path  === '/sub-jump') {
+    next('/sub-jump')
+    return
   }
 
   if (to.path === "/"){

+ 21 - 6
src/utils/loginUtils.js

@@ -156,7 +156,7 @@ const loginLogic = async (loginForm, tenantId, isAuthorized, router, loginPath =
     let res
     // 构建请求头,只有当 tenantId 存在时才添加 Tenant-Id
     const headers = tenantId ? { 'Tenant-Id': tenantId } : {}
-    
+
     if (!isAuthorized.value) {
       // 未授权状态,使用短信验证码登录
       res = await smsLogin(
@@ -219,6 +219,16 @@ const loginLogic = async (loginForm, tenantId, isAuthorized, router, loginPath =
 
       // 登录成功后,跳转到默认页面
       loginPath = loginPath || managementRoutes.home
+
+      // 登录成功后(判断是否是由子程序过来的)
+      const redirect = localStorage.getItem('loginRedirect')
+      if (redirect) {
+        localStorage.removeItem('loginRedirect')
+        window.location.href = decodeURIComponent(redirect)
+        return true
+      }
+
+      //默认登录成功主页
       router.push(loginPath)
 
       return true
@@ -333,7 +343,7 @@ const autoLogin = async (tenantName, username, password, router, redirectPath) =
 
     // 构建请求头,只有当 tenantId 存在时才添加 Tenant-Id
     const headers = tenantId ? { 'Tenant-Id': tenantId } : {}
-    
+
     // 执行登录
     const res = await login(
       headers,
@@ -389,9 +399,14 @@ const logoutLogic = async (router, redirectPath = homeRoutes.login) => {
     //清除本地存储
     removeLocalStorage();
 
+    localStorage.clear();
+    sessionStorage.clear()
+    //JS删除跨域共享access_token Cookie(httpOnly=false才生效)
+    document.cookie = "access_token=; Max-Age=0; Domain=.learn-ai.com.cn; Path=/; Secure; SameSite=None";
+
     // 检查是否勾选了记住我
     const rememberMe = localStorage.getItem('rememberMe') === 'true'
-    
+
     if (!rememberMe) {
       // 未勾选记住我,清空所有信息
       localStorage.removeItem('userName')
@@ -407,10 +422,10 @@ const logoutLogic = async (router, redirectPath = homeRoutes.login) => {
 
     //清除本地存储
     removeLocalStorage();
-    
+
     // 检查是否勾选了记住我
     const rememberMe = localStorage.getItem('rememberMe') === 'true'
-    
+
     if (!rememberMe) {
       // 未勾选记住我,清空所有信息
       localStorage.removeItem('userName')
@@ -472,4 +487,4 @@ export {
   autoLogin,
   logoutLogic,
   removeLocalStorageKey
-}
+}

+ 12 - 15
src/utils/request.js

@@ -64,7 +64,7 @@ request.interceptors.response.use(function (response) {
 // ajax 自定义各种数据请求的方法
 export default function ajax (config) {
   // 1. 先获取到请求的一些必要参数
-  const { url = '', method = 'GET', data = {}, headers = {} } = config
+  const { url = '', method = 'GET', data = {}, headers = {}, withCredentials = true  } = config
   // 2. 判断我们请求的类型是 get 还是 post 还是其他
   switch (method.toUpperCase()) {
     case 'GET':
@@ -75,10 +75,10 @@ export default function ajax (config) {
         for (const key in data) {
           obj.append(key, data[key])
         }
-        return request.post(url, obj, { headers })
+        return request.post(url, obj, { headers, withCredentials })
       }
       // get 请求的参数我们需要放在 params 中
-      return request.get(url, { params: data })
+      return request.get(url, { params: data, withCredentials })
     case 'POST':
       //  post  请求
       // 1. 表单提交数据
@@ -88,7 +88,7 @@ export default function ajax (config) {
         for (const key in data) {
           obj.append(key, data[key])
         }
-        return request.post(url, obj, { headers })
+        return request.post(url, obj, { headers, withCredentials })
       }
       // 2. 文件数据
       if (headers['content-type'] == 'multipart/form-data') {
@@ -96,21 +96,18 @@ export default function ajax (config) {
         for (const key in data) {
           obj.append(key, data[key])
         }
-        return request.post(url, obj, { headers })
+        return request.post(url, obj, { headers, withCredentials })
       }
       // 3. json 数据
-      return request.post(url, data, {headers})
+      return request.post(url, data, {headers, withCredentials})
     case 'PUT':
-      // 通常用来修改数据用的 --- 数据更新
-      return request.put(url, data)
+      return request.put(url, data, { withCredentials })
     case 'DELETE':
-      // 删除数据
-      return request.delete(url, { data })
+      return request.delete(url, { data, withCredentials })
     case 'PATCH':
-      // 更新局部资源
-      return request.patch(url, data)
+      return request.patch(url, data, { data, withCredentials })
     default:
-      // 如果前面全部都不是
-      return request.request(config)
+      // 兜底原样透传全部config
+      return request.request({...config, withCredentials})
   }
-}
+}

+ 11 - 2
src/views/Login.vue

@@ -187,8 +187,17 @@ onMounted(() => {
   // 加载本地存储的登录数据
   loadLoginData(loginData)
 
-  if (Object.keys(router.currentRoute.value.query).length > 0) {
-    // 其他参数,重定向到登录页
+  // 保存 redirect 或 callback 参数(用于从其他程序跳转登录后重定向)
+  const query = router.currentRoute.value.query
+  const redirect = query.redirect || query.callback
+  if (redirect) {
+    localStorage.setItem('loginRedirect', redirect)
+  } else {
+    localStorage.removeItem('loginRedirect')
+  }
+
+  // 原有逻辑:清理登录页的 query 参数,保持登录页干净
+  if (Object.keys(query).length > 0) {
     router.replace(homeRoutes.login)
   }