From 2d019f1bf96b94e879b79ad83e13c5eea12a94bd Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 7 Apr 2023 01:45:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SSO=E5=8D=95=E7=82=B9?= =?UTF-8?q?=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/login/index.ts | 44 +++++ src/config/axios/service.ts | 4 +- src/locales/zh-CN.ts | 7 + src/router/index.ts | 4 +- src/router/modules/remaining.ts | 10 + src/types/auto-components.d.ts | 14 +- src/views/Login/Login.vue | 20 +- src/views/Login/components/LoginForm.vue | 11 +- src/views/Login/components/LoginFormTitle.vue | 3 +- src/views/Login/components/SSOLogin.vue | 177 ++++++++++++++++++ src/views/Login/components/index.ts | 3 +- src/views/Login/components/useLogin.ts | 3 +- 12 files changed, 277 insertions(+), 23 deletions(-) create mode 100644 src/views/Login/components/SSOLogin.vue diff --git a/src/api/login/index.ts b/src/api/login/index.ts index 0c895663..bc60e8c9 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -1,16 +1,19 @@ import request from '@/config/axios' import { getRefreshToken } from '@/utils/auth' import type { UserLoginVO } from './types' +import { service } from '@/config/axios/service' export interface CodeImgResult { captchaOnOff: boolean img: string uuid: string } + export interface SmsCodeVO { mobile: string scene: number } + export interface SmsLoginVO { mobile: string code: string @@ -71,3 +74,44 @@ export const getCodeApi = (data) => { export const reqCheckApi = (data) => { return request.postOriginal({ url: 'system/captcha/check', data }) } + +// ========== OAUTH 2.0 相关 ========== + +export const getAuthorize = (clientId) => { + return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId }) +} + +export function authorize( + responseType: string, + clientId: string, + redirectUri: string, + state: string, + autoApprove: boolean, + checkedScopes: any, + uncheckedScopes: any +) { + // 构建 scopes + const scopes = {} + for (const scope of checkedScopes) { + scopes[scope] = true + } + for (const scope of uncheckedScopes) { + scopes[scope] = false + } + // 发起请求 + return service({ + url: '/system/oauth2/authorize', + headers: { + 'Content-type': 'application/x-www-form-urlencoded' + }, + params: { + response_type: responseType, + client_id: clientId, + redirect_uri: redirectUri, + state: state, + auto_approve: autoApprove, + scope: JSON.stringify(scopes) + }, + method: 'post' + }) +} diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts index afe75d8a..d37dfb06 100644 --- a/src/config/axios/service.ts +++ b/src/config/axios/service.ts @@ -1,8 +1,8 @@ import axios, { + AxiosError, AxiosInstance, AxiosRequestHeaders, AxiosResponse, - AxiosError, InternalAxiosRequestConfig } from 'axios' @@ -230,7 +230,7 @@ const handleAuthorized = () => { wsCache.clear() removeToken() isRelogin.show = false - window.location.href = '/' + window.location.href = '/login?redirect=/sso?' + window.location.href.split('?')[1] }) } return Promise.reject(t('sys.api.timeoutMessage')) diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 6f46f1ab..e139fe62 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -129,6 +129,12 @@ export default { btnMobile: '手机登录', btnQRCode: '二维码登录', qrcode: '扫描二维码登录', + sso: { + user: { + read: '访问你的个人信息', + write: '修改你的个人信息' + } + }, btnRegister: '注册', SmsSendMsg: '验证码已发送' }, @@ -353,6 +359,7 @@ export default { login: { backSignIn: '返回', signInFormTitle: '登录', + ssoFormTitle: '三方授权', mobileSignInFormTitle: '手机登录', qrSignInFormTitle: '二维码登录', signUpFormTitle: '注册', diff --git a/src/router/index.ts b/src/router/index.ts index 02d913f8..8f66ca31 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,11 +1,11 @@ import type { App } from 'vue' import type { RouteRecordRaw } from 'vue-router' -import { createRouter, createWebHashHistory } from 'vue-router' +import { createRouter, createWebHistory } from 'vue-router' import remainingRouter from './modules/remaining' // 创建路由实例 const router = createRouter({ - history: createWebHashHistory(), // createWebHashHistory URL带#,createWebHistory URL不带# + history: createWebHistory(), // createWebHashHistory URL带#,createWebHistory URL不带# strict: true, routes: remainingRouter as RouteRecordRaw[], scrollBehavior: () => ({ left: 0, top: 0 }) diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 2dc9522d..ff4c99ad 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -185,6 +185,16 @@ const remainingRouter: AppRouteRecordRaw[] = [ noTagsView: true } }, + { + path: '/sso', + component: () => import('@/views/Login/Login.vue'), + name: 'SSOLogin', + meta: { + hidden: true, + title: t('router.login'), + noTagsView: true + } + }, { path: '/403', component: () => import('@/views/Error/403.vue'), diff --git a/src/types/auto-components.d.ts b/src/types/auto-components.d.ts index 8851767a..ac142784 100644 --- a/src/types/auto-components.d.ts +++ b/src/types/auto-components.d.ts @@ -23,13 +23,12 @@ declare module '@vue/runtime-core' { DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default'] Echart: typeof import('./../components/Echart/src/Echart.vue')['default'] Editor: typeof import('./../components/Editor/src/Editor.vue')['default'] - ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer'] - ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElBadge: typeof import('element-plus/es')['ElBadge'] ElButton: typeof import('element-plus/es')['ElButton'] ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCard: typeof import('element-plus/es')['ElCard'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElCol: typeof import('element-plus/es')['ElCol'] ElCollapse: typeof import('element-plus/es')['ElCollapse'] ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] @@ -54,34 +53,23 @@ declare module '@vue/runtime-core' { ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElIcon: typeof import('element-plus/es')['ElIcon'] - ElImage: typeof import('element-plus/es')['ElImage'] ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] ElInput: typeof import('element-plus/es')['ElInput'] - ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElLink: typeof import('element-plus/es')['ElLink'] ElOption: typeof import('element-plus/es')['ElOption'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] - ElRadio: typeof import('element-plus/es')['ElRadio'] - ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] - ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] - ElSpace: typeof import('element-plus/es')['ElSpace'] ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - ElTableV2: typeof import('element-plus/es')['ElTableV2'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabs: typeof import('element-plus/es')['ElTabs'] - ElTag: typeof import('element-plus/es')['ElTag'] - ElTimeline: typeof import('element-plus/es')['ElTimeline'] - ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTree: typeof import('element-plus/es')['ElTree'] - ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] ElUpload: typeof import('element-plus/es')['ElUpload'] Error: typeof import('./../components/Error/src/Error.vue')['default'] FlowCondition: typeof import('./../components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue')['default'] diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue index a513b0ca..4bd9ff90 100644 --- a/src/views/Login/Login.vue +++ b/src/views/Login/Login.vue @@ -52,6 +52,11 @@ + + @@ -65,12 +70,25 @@ import { useDesign } from '@/hooks/web/useDesign' import { useAppStore } from '@/store/modules/app' import { ThemeSwitch } from '@/layout/components/ThemeSwitch' import { LocaleDropdown } from '@/layout/components/LocaleDropdown' -import { LoginForm, MobileForm, RegisterForm, QrCodeForm } from './components' + +import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components' +import { RouteLocationNormalizedLoaded } from 'vue-router' const { t } = useI18n() const appStore = useAppStore() const { getPrefixCls } = useDesign() const prefixCls = getPrefixCls('login') +// =======SSO====== +const isSSO = ref(false) +const router = useRouter() +// 监听当前路由 +watch( + () => router.currentRoute.value, + (route: RouteLocationNormalizedLoaded) => { + if (route.name === 'SSOLogin') isSSO.value = true + }, + { immediate: true } +)