完善SSO单点登录

(cherry picked from commit e22363d061)
This commit is contained in:
puhui999 2023-04-07 10:15:21 +08:00 committed by shizhong
parent 1103f8ff39
commit fbff879504
4 changed files with 43 additions and 42 deletions

View File

@ -76,7 +76,14 @@ export const reqCheckApi = (data) => {
} }
// ========== OAUTH 2.0 相关 ========== // ========== OAUTH 2.0 相关 ==========
export type scopesType = string[]
export interface paramsType {
responseType: string
clientId: string
redirectUri: string
state: string
scopes: scopesType
}
export const getAuthorize = (clientId) => { export const getAuthorize = (clientId) => {
return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId }) return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId })
} }
@ -87,8 +94,8 @@ export function authorize(
redirectUri: string, redirectUri: string,
state: string, state: string,
autoApprove: boolean, autoApprove: boolean,
checkedScopes: any, checkedScopes: scopesType,
uncheckedScopes: any uncheckedScopes: scopesType
) { ) {
// 构建 scopes // 构建 scopes
const scopes = {} const scopes = {}

View File

@ -9,19 +9,19 @@
> >
<!-- 左上角的 logo + 系统标题 --> <!-- 左上角的 logo + 系统标题 -->
<div class="flex items-center relative text-white"> <div class="flex items-center relative text-white">
<img src="@/assets/imgs/logo.png" alt="" class="w-48px h-48px mr-10px" /> <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" />
<span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span> <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span>
</div> </div>
<!-- 左边的背景图 + 欢迎语 --> <!-- 左边的背景图 + 欢迎语 -->
<div class="flex justify-center items-center h-[calc(100%-60px)]"> <div class="flex justify-center items-center h-[calc(100%-60px)]">
<TransitionGroup <TransitionGroup
appear appear
tag="div"
enter-active-class="animate__animated animate__bounceInLeft" enter-active-class="animate__animated animate__bounceInLeft"
tag="div"
> >
<img src="@/assets/svgs/login-box-bg.svg" key="1" alt="" class="w-350px" /> <img key="1" alt="" class="w-350px" src="@/assets/svgs/login-box-bg.svg" />
<div class="text-3xl text-white" key="2">{{ t('login.welcome') }}</div> <div key="2" class="text-3xl text-white">{{ t('login.welcome') }}</div>
<div class="mt-5 font-normal text-white text-14px" key="3"> <div key="3" class="mt-5 font-normal text-white text-14px">
{{ t('login.message') }} {{ t('login.message') }}
</div> </div>
</TransitionGroup> </TransitionGroup>
@ -31,7 +31,7 @@
<!-- 右上角的主题语言选择 --> <!-- 右上角的主题语言选择 -->
<div class="flex justify-between items-center text-white @2xl:justify-end @xl:justify-end"> <div class="flex justify-between items-center text-white @2xl:justify-end @xl:justify-end">
<div class="flex items-center @2xl:hidden @xl:hidden"> <div class="flex items-center @2xl:hidden @xl:hidden">
<img src="@/assets/imgs/logo.png" alt="" class="w-48px h-48px mr-10px" /> <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" />
<span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span> <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span>
</div> </div>
<div class="flex justify-end items-center space-x-10px"> <div class="flex justify-end items-center space-x-10px">
@ -52,18 +52,15 @@
<QrCodeForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" /> <QrCodeForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
<!-- 注册 --> <!-- 注册 -->
<RegisterForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" /> <RegisterForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
<!-- 三方登录 v-if触发组件初始化 --> <!-- 三方登录 -->
<SSOLoginVue <SSOLoginVue class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
v-if="isSSO"
class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)"
/>
</div> </div>
</Transition> </Transition>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script lang="ts" setup>
import { underlineToHump } from '@/utils' import { underlineToHump } from '@/utils'
import { useDesign } from '@/hooks/web/useDesign' import { useDesign } from '@/hooks/web/useDesign'
@ -72,23 +69,11 @@ import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
import { LocaleDropdown } from '@/layout/components/LocaleDropdown' import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components' import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components'
import { RouteLocationNormalizedLoaded } from 'vue-router'
const { t } = useI18n() const { t } = useI18n()
const appStore = useAppStore() const appStore = useAppStore()
const { getPrefixCls } = useDesign() const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('login') 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 }
)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -279,7 +279,6 @@ const doSocialLogin = async (type: number) => {
watch( watch(
() => currentRoute.value, () => currentRoute.value,
(route: RouteLocationNormalizedLoaded) => { (route: RouteLocationNormalizedLoaded) => {
if (route.name === 'SSOLogin') setLoginState(LoginStateEnum.SSO)
redirect.value = route?.query?.redirect as string redirect.value = route?.query?.redirect as string
}, },
{ {

View File

@ -1,6 +1,7 @@
<template> <template>
<!-- 表单 --> <!-- 表单 -->
<div class="form-cont"> <div v-show="getShow" class="form-cont">
<!-- <LoginFormTitle style="width: 100%" />-->
<el-tabs class="form" style="float: none" value="uname"> <el-tabs class="form" style="float: none" value="uname">
<el-tab-pane :label="'三方授权(' + client.name + ')'" name="uname" /> <el-tab-pane :label="'三方授权(' + client.name + ')'" name="uname" />
</el-tabs> </el-tabs>
@ -12,8 +13,8 @@
<el-checkbox-group v-model="loginForm.scopes"> <el-checkbox-group v-model="loginForm.scopes">
<el-checkbox <el-checkbox
v-for="scope in params.scopes" v-for="scope in params.scopes"
:label="scope"
:key="scope" :key="scope"
:label="scope"
style="display: block; margin-bottom: -10px" style="display: block; margin-bottom: -10px"
>{{ formatScope(scope) }} >{{ formatScope(scope) }}
</el-checkbox> </el-checkbox>
@ -24,8 +25,8 @@
<el-button <el-button
:loading="loading" :loading="loading"
size="small" size="small"
type="primary"
style="width: 60%" style="width: 60%"
type="primary"
@click.prevent="handleAuthorize(true)" @click.prevent="handleAuthorize(true)"
> >
<span v-if="!loading">同意授权</span> <span v-if="!loading">同意授权</span>
@ -40,19 +41,15 @@
</div> </div>
</template> </template>
<script lang="ts" name="SSOLogin" setup> <script lang="ts" name="SSOLogin" setup>
import { authorize, getAuthorize } from '@/api/login' // import LoginFormTitle from './LoginFormTitle.vue' // TODO
import { authorize, getAuthorize, paramsType, scopesType } from '@/api/login'
import { LoginStateEnum, useLoginState } from './useLogin'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
const { t } = useI18n() const { t } = useI18n()
const ssoForm = ref() // Ref const ssoForm = ref() // Ref
const { getLoginState, setLoginState } = useLoginState()
type scopesType = string[] const getShow = computed(() => unref(getLoginState) === LoginStateEnum.SSO)
interface paramsType {
responseType: string
clientId: string
redirectUri: string
state: string
scopes: scopesType
}
const loginForm = reactive<{ scopes: scopesType }>({ const loginForm = reactive<{ scopes: scopesType }>({
scopes: [] // scope scopes: [] // scope
}) })
@ -116,6 +113,7 @@ const doAuthorize = (autoApprove, checkedScopes, uncheckedScopes) => {
const formatScope = (scope) => { const formatScope = (scope) => {
// scope 便 // scope 便
// demo "system_oauth2_scope" scope // demo "system_oauth2_scope" scope
// TODO
return t(`login.sso.${scope}`) return t(`login.sso.${scope}`)
} }
const route = useRoute() const route = useRoute()
@ -146,7 +144,6 @@ const init = () => {
// //
getAuthorize(params.clientId).then((res) => { getAuthorize(params.clientId).then((res) => {
console.log(res)
client.value = res.client client.value = res.client
// scope // scope
let scopes let scopes
@ -173,5 +170,18 @@ const init = () => {
} }
}) })
} }
// =======SSO======
const { currentRoute } = useRouter()
//
watch(
() => currentRoute.value,
(route: RouteLocationNormalizedLoaded) => {
if (route.name === 'SSOLogin') {
setLoginState(LoginStateEnum.SSO)
init()
}
},
{ immediate: true }
)
init() init()
</script> </script>