Sfoglia il codice sorgente

前端授权登录

liutao 1 settimana fa
parent
commit
77f694e6ff

+ 4 - 1
CYZZ-master/cyzz/web_cyzz/public/config.js

@@ -11,7 +11,10 @@
       encryption: true, // 是否加密
       secretKey: 'yydjydhfyhfggd'
     },
-
+    authorization: {
+      enabled: true,
+      time: 12
+    },
     server: 'http://localhost:8517',
     // server_hgzt: 'http://121.40.148.47:8530/ilpes_st',
     server_hgzt: 'http://121.40.148.47:8530/ilpes_st',

+ 75 - 1
CYZZ-master/cyzz/web_cyzz/src/App.vue

@@ -18,10 +18,11 @@
 <script setup>
 import { RouterView } from 'vue-router';
 import { onBeforeMount, ref } from 'vue';
-
+import { setLocalStorageWithExpiry, getLocalStorageWithExpiry } from '@/utils/store.js'
 import zhCN from 'ant-design-vue/es/locale/zh_CN';
 import dayjs from 'dayjs';
 import 'dayjs/locale/zh-cn';
+import http from "@/utils/http";
 dayjs.locale('zh-cn');
 
 const locale = ref(zhCN)
@@ -29,7 +30,80 @@ const locale = ref(zhCN)
 onBeforeMount(() => {
   document.title = window?.AppGlobalConfig?.system?.name || '';
 })
+const route = useRoute();
+const router = useRouter();
+const foundHandle = () => {
+  router.push({
+    name: '404'
+  })
+}
+const ticketStr = ref()
+const getUrlParamByToken = () => {
+  if (!window?.AppGlobalConfig?.authorization?.enabled) return;
+  const routePath = route.path
+  if (routePath.indexOf('404') !== -1) { return }
+  const isLogin = getLocalStorageWithExpiry("_isLogin")
+  if(isLogin === '1') return
+  var urlStr = window.location.href
+  var arr = urlStr.split('?')
+  if (arr.length === 1) {
+    foundHandle()
+    return
+  }
+
+  var paramStr = arr[1]
+  var paramArr = paramStr.split('&')
+  var paramMap = {}
+  paramArr.forEach(item => {
+    var arr = item.split('=')
+    paramMap[arr[0]] = arr[1]
+  })
+  if (paramMap["debugger"] == "1") {
+      return;
+  }
+  if (!paramMap.hasOwnProperty('sykjzlptv2_ticket')) {
+    foundHandle()
+    return
+  }
+  ticketStr.value = paramMap['sykjzlptv2_ticket']
+  const storeTicketStr = localStorage.getItem('_sykjzlptv2_ticket')
+  if (storeTicketStr) {
+    if (storeTicketStr === paramMap['sykjzlptv2_ticket']) {
+      return
+    }
+  }
+  localStorage.removeItem('sykjzlptv2_ticket')
+  getCommonToken()
+}
+
+const getCommonToken = async () => {
+  if (!ticketStr.value) { return }
+  const urlApi = `/auth/ticket`
+  var p = { ticket: ticketStr.value };
+  http.get(urlApi, p, this, false).then(async (resultData) => {
+    if (!resultData || resultData['error_code']) {
+      message.error('用户不合法,请核实用户信息!')
+      foundHandle()
+      return
+    }
+    if (resultData['error']) {
+      message.error(resultData['error'])
+      foundHandle()
+      return
+    }
+    if(resultData['syUser']){
+      const syUserObj = resultData["syUser"];
+      store.updateUser({
+        syUser: syUserObj
+      })
+      // getByUser(syUserObj['UserName'], syUserObj['Id'])
+      setLocalStorageWithExpiry("_isLogin", "1", 3600000 * window?.AppGlobalConfig?.authorization?.time);
+      localStorage.setItem("_sykjzlptv2_ticket", ticketStr.value);
+    }
+  });
+}
 
+getUrlParamByToken()
 </script>
 
 <style scoped lang="scss">

+ 6 - 1
CYZZ-master/cyzz/web_cyzz/src/router/routes-all.js

@@ -3,5 +3,10 @@ export default [
     path: '/djyc',
     name: 'land-use-page',
     component: () => import('@/views/land-use/PolicyCoordination.vue'),
+  }, {
+    path: '/404',
+    name: '404',
+    meta: { title: '404' },
+    component: () => import('@/views/404/index.vue'),
   },
-  ]
+]

+ 155 - 0
CYZZ-master/cyzz/web_cyzz/src/utils/http.ts

@@ -0,0 +1,155 @@
+import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
+
+const windowConfig = (window as any).AppGlobalConfig;
+
+// 创建 axios 实例
+const http: AxiosInstance = axios.create({
+  baseURL: windowConfig.server,
+  timeout: 30000, // 请求超时时间
+});
+
+const Authorization = windowConfig?.authToken ?? "Authorization";
+// 请求拦截器
+http.interceptors.request.use(
+  (config: any) => {
+    const token = localStorage.getItem("token");
+    if (token) {
+      config.headers = {
+        ...config.headers,
+        [Authorization]: token,
+      };
+    }
+    return config;
+  },
+  (error) => Promise.reject(error)
+);
+
+// 响应拦截器
+http.interceptors.response.use(
+  (response: AxiosResponse) => {
+    // 检查响应类型,如果是文件类型,直接返回
+    const contentType = response.headers["content-type"];
+    if (
+      (contentType && contentType.includes("application/octet-stream")) ||
+      response.config.responseType === "blob"
+    ) {
+      return response; // 直接返回文件数据
+    }
+
+    // 大模型类接口请求体,直接返回全部内容
+    if (response.status && response.status == 200) {
+      return response.data; // 直接返回有效数据
+    }
+
+    // 处理非文件类型的响应
+    if (response.data.code !== 200) {
+      console.error(`Error: ${response.data.message}`);
+      return Promise.reject(new Error(response.data.message));
+    }
+
+    return response.data;
+  },
+  (error) => {
+    console.error(error.response?.data || error.message);
+    return Promise.reject(error);
+  }
+);
+
+// 封装实例方法
+class HttpRequest {
+  private instance: AxiosInstance;
+
+  constructor(instance: AxiosInstance) {
+    this.instance = instance;
+  }
+  get<T = any>(
+    url: string,
+    params?: Record<string, any>,
+    config?: AxiosRequestConfig
+  ): Promise<T> {
+    if (config?.baseURL) {
+      this.instance.baseURL = config.baseURL;
+    }
+    return this.instance
+      .get<T>(url, { ...config, params })
+      .then((response) => response as T);
+  }
+
+  post<T = any>(
+    url: string,
+    data?: Record<string, any>,
+    config?: AxiosRequestConfig
+  ): Promise<T> {
+    return this.instance
+      .post<T>(url, data, config)
+      .then((response) => response as T);
+  }
+
+  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
+    return this.instance
+      .delete<T>(url, config)
+      .then((response) => response as T);
+  }
+
+  // 下载文件方法,支持 GET 和 POST
+  download(
+    method: "GET" | "POST",
+    url: string,
+    options: {
+      params?: Record<string, any>; // get 请求参数
+      data?: Record<string, any>; // post 请求参数
+      config?: AxiosRequestConfig; // Axios 配置
+    } = {}
+  ): Promise<void> {
+    const { params, data, config } = options;
+
+    // 设置响应类型为 blob
+    const axiosConfig: AxiosRequestConfig = {
+      ...config,
+      responseType: "blob",
+    };
+
+    // 选择请求方法
+    const request =
+      method === "GET"
+        ? this.instance.get(url, { ...axiosConfig, params })
+        : this.instance.post(url, data, axiosConfig);
+
+    return request
+      .then((response) => {
+        console.log("response", response);
+        const blob = new Blob([response.data]);
+        const contentDisposition = response.headers["content-disposition"];
+        const defaultFileName = "downloaded-file.zip"; // 默认文件名
+        let fileName = defaultFileName;
+
+        // 从 Content-Disposition 获取文件名
+        if (contentDisposition) {
+          const match = contentDisposition.match(/filename="?(.+)"?/);
+          if (match && match[1]) {
+            fileName = decodeURIComponent(match[1]);
+          }
+        }
+
+        // 创建下载链接
+        const downloadUrl = window.URL.createObjectURL(blob);
+        const a = document.createElement("a");
+        a.href = downloadUrl;
+        a.download = fileName;
+        a.style.display = "none";
+        document.body.appendChild(a);
+        a.click();
+        window.URL.revokeObjectURL(downloadUrl); // 释放 URL
+        document.body.removeChild(a);
+      })
+      .catch((error) => {
+        console.error("Download failed:", error);
+        return Promise.reject(error);
+      });
+  }
+}
+
+// 实例化封装
+const api = new HttpRequest(http);
+
+export default api;

+ 24 - 0
CYZZ-master/cyzz/web_cyzz/src/utils/store.js

@@ -0,0 +1,24 @@
+export function setLocalStorageWithExpiry(key, value, ttl) {
+    const now = new Date();
+    // `item`是一个对象,包含了值和过期时间
+    const item = {
+        value: value,
+        expiry: now.getTime() + ttl,
+    };
+    localStorage.setItem(key, JSON.stringify(item));
+}
+ 
+export function getLocalStorageWithExpiry(key) {
+    const itemStr = localStorage.getItem(key);
+    // 如果没有找到或者已经过期,返回null
+    if (!itemStr) {
+        return null;
+    }
+    const item = JSON.parse(itemStr);
+    const now = new Date();
+    if (now.getTime() > item.expiry) {
+        localStorage.removeItem(key);
+        return null;
+    }
+    return item.value;
+}

+ 22 - 0
CYZZ-master/cyzz/web_cyzz/src/views/404/index.vue

@@ -0,0 +1,22 @@
+
+
+<template>
+  <div class="no_auth_box">
+    <!-- <img src="../../assets/images/no_auth.png" /> -->
+    <p>抱歉,您暂无当前页面的访问权限,请联系管理员</p>
+  </div>
+</template>
+
+<script setup>
+
+</script>
+
+<style lang="scss" scoped>
+.no_auth_box {
+  text-align: center;
+  >p {
+    color: #373C45;
+    font-size: 20px;
+  }
+}
+</style>