fix: 接入cas单点登录
parent
ad9a90e252
commit
a4d103790d
|
@ -37,7 +37,7 @@ onMounted(() => {
|
|||
}, 1000 * 2)
|
||||
})
|
||||
const showMainApp = computed(() => {
|
||||
return ['/login', '/sso', '/lockme', '/redirect', '/404', '/license'].includes(route.path)
|
||||
return ['/login', '/caslogin', '/sso', '/lockme', '/redirect', '/404', '/license'].includes(route.path)
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@media screen and(-ms-high-contrast:active),
|
||||
@media screen and (-ms-high-contrast:active),
|
||||
(-ms-high-contrast:none) {
|
||||
.el-table__header,
|
||||
.el-table__body {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template>
|
||||
<template>
|
||||
<a-dropdown>
|
||||
<div class="user-content">
|
||||
<img :src="userData.portrait" class="head-portrait" />
|
||||
|
@ -32,6 +32,7 @@
|
|||
import crypto from 'utils/crypto.js'
|
||||
import { changePassword } from '@/services/manager'
|
||||
import { logout } from 'services'
|
||||
import { getCasConfig } from '@/store/utils'
|
||||
import InfoDialog from './InfoDialog.vue'
|
||||
import { computed, defineComponent, ref, createVNode } from 'vue'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
|
@ -105,9 +106,15 @@ export default defineComponent({
|
|||
icon: createVNode(ExclamationCircleOutlined),
|
||||
content: '您确定要退出该系统吗?',
|
||||
async onOk() {
|
||||
const res = await logout()
|
||||
if (res.success) {
|
||||
store.dispatch('permission/ResetRoutes')
|
||||
const { isCASLogin, casLogoutPath } = await getCasConfig()
|
||||
if (isCASLogin) {
|
||||
location.href = casLogoutPath
|
||||
} else {
|
||||
const res = await logout()
|
||||
if (res.success) {
|
||||
await store.dispatch('permission/ResetRoutes', false)
|
||||
location.href = '/login'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -6,23 +6,42 @@ import router from './router'
|
|||
import { getToken, setToken } from 'utils/auth'
|
||||
import { getQuery } from 'utils'
|
||||
import { isEmpty, assign } from 'lodash-es'
|
||||
import { getCasConfig, goLogin } from './store/utils'
|
||||
|
||||
const redirectToCasLogin = (to, next, ticket, casLoginPath) => {
|
||||
if (!ticket) {
|
||||
location.href = casLoginPath
|
||||
return
|
||||
}
|
||||
if (to.path === '/caslogin') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
next(`/caslogin?ticket=${ticket}`)
|
||||
}
|
||||
|
||||
const { token } = getQuery(location.hash)
|
||||
if (token) {
|
||||
setToken(token)
|
||||
}
|
||||
|
||||
const whiteList = ['/login', '/404', '/401', '/license', '/sso']
|
||||
const whiteList = ['/login', '/caslogin', '/404', '/401', '/license', '/sso']
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const ticket = to.query.ticket || new URLSearchParams(location.search).get('ticket')
|
||||
if (isEmpty(history.state.current)) {
|
||||
assign(history.state, { current: from.fullPath })
|
||||
}
|
||||
if (getToken()) {
|
||||
// 判断用户是否处于登录状态
|
||||
if (to.path === '/login') {
|
||||
if (to.path === '/login' || to.path === '/caslogin') {
|
||||
// 如果已经登录重定向到主页
|
||||
await store.dispatch('permission/ResetRoutes', false)
|
||||
next('/login')
|
||||
const { isCASLogin, casLoginPath } = await getCasConfig()
|
||||
if (!isCASLogin) {
|
||||
next('/login')
|
||||
} else {
|
||||
redirectToCasLogin(to, next, ticket, casLoginPath)
|
||||
}
|
||||
} else {
|
||||
// 为null的场景: 刷新页面或者新开窗口;
|
||||
const addRoutes = store.getters.addRoutes
|
||||
|
@ -36,7 +55,12 @@ router.beforeEach(async (to, from, next) => {
|
|||
} catch (error) {
|
||||
// remove token and go to login page to re-login
|
||||
await store.dispatch('permission/ResetRoutes', false)
|
||||
next('/login')
|
||||
const { isCASLogin, casLoginPath } = await getCasConfig()
|
||||
if (!isCASLogin) {
|
||||
next('/login')
|
||||
} else {
|
||||
redirectToCasLogin(to, next, ticket, casLoginPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +68,14 @@ router.beforeEach(async (to, from, next) => {
|
|||
// 用户没有登录
|
||||
if (whiteList.includes(to.path)) {
|
||||
// 在白名单里直接跳转
|
||||
next()
|
||||
const { isCASLogin, casLoginPath } = await getCasConfig()
|
||||
if (!isCASLogin) {
|
||||
next()
|
||||
} else {
|
||||
redirectToCasLogin(to, next, ticket, casLoginPath)
|
||||
}
|
||||
} else {
|
||||
next('/login')
|
||||
goLogin()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -5,7 +5,12 @@ const routes: RouteRecordRaw[] = [
|
|||
{
|
||||
name: 'Login',
|
||||
path: '/login',
|
||||
component: () => import('views/login/login.vue')
|
||||
component: () => import('views/login/userLogin.vue')
|
||||
},
|
||||
{
|
||||
name: 'CASLogin',
|
||||
path: '/caslogin',
|
||||
component: () => import('views/login/casLogin.vue')
|
||||
},
|
||||
{
|
||||
path: '/sso',
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
import request from 'utils/request'
|
||||
import { wrapperParams } from 'utils'
|
||||
|
||||
export function loginByCas(params) {
|
||||
return request.post('/sms/v1/users/login/cas', wrapperParams(params))
|
||||
}
|
||||
|
||||
export function login(params) {
|
||||
return request.post('/sms/v1/users/login', params)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { getUserPermissions } from 'services'
|
|||
import BlankView from '@/layouts/blank.vue'
|
||||
import router, { resetRouter } from '@/router'
|
||||
import { menuKey, enablePermissionStorage } from '@/config'
|
||||
import { urlToList } from '../utils'
|
||||
import { urlToList, goLogin } from '../utils'
|
||||
import actionStore from '@/core/actions'
|
||||
|
||||
const resultRoutes = []
|
||||
|
@ -167,7 +167,7 @@ const actions = {
|
|||
// 重置标签信息
|
||||
dispatch('tagsView/delAllViews', null, { root: true })
|
||||
removeToken()
|
||||
if (redirectToLogin) window.location.href = '/login'
|
||||
if (redirectToLogin) goLogin()
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { getSystemConfigs } from 'services'
|
||||
import store from '@/store'
|
||||
export const setBrowser = (icon, title) => {
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
const linkTag = document.createElement('link')
|
||||
|
@ -12,3 +14,32 @@ export const urlToList = (url) => {
|
|||
const urllist = url.split('/').filter((i) => i)
|
||||
return urllist.map((urlItem, index) => `/${urllist.slice(0, index + 1).join('/')}`)
|
||||
}
|
||||
export const getPageConfigs = async () => {
|
||||
const res = await getSystemConfigs({ category: '界面配置' })
|
||||
if (res.success) {
|
||||
return res.data
|
||||
}
|
||||
throw res.data
|
||||
}
|
||||
export const getCasConfig = async () => {
|
||||
const Store = store
|
||||
let pageConfig = Store?.getters?.pageConfig || {}
|
||||
if (!Object.keys(pageConfig).length) {
|
||||
pageConfig = (await getPageConfigs()) || {}
|
||||
}
|
||||
const { cas, casLoginUrl, casLoginoutUrl } = pageConfig
|
||||
const isCASLogin = (cas === 'true' || cas === true) && !!casLoginUrl
|
||||
const casLoginPath = `${casLoginUrl}?service=${location.origin}/caslogin`
|
||||
const casLogoutPath = `${casLoginoutUrl}?service=${location.origin}/caslogin`
|
||||
return { isCASLogin, cas, casLoginPath, casLogoutPath }
|
||||
}
|
||||
export const goLogin = async (forceCasRedirect = false) => {
|
||||
const { isCASLogin, casLoginPath } = await getCasConfig()
|
||||
let path = '/login'
|
||||
// forceCasRedirect avoids reusing stale CAS tickets during logout or failed auth attempts
|
||||
const ticket = forceCasRedirect ? null : new URLSearchParams(location.search).get('ticket')
|
||||
if (isCASLogin) {
|
||||
path = ticket ? `/caslogin?ticket=${ticket}` : casLoginPath
|
||||
}
|
||||
window.location.href = path
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import 'nprogress/nprogress.css'
|
|||
import { notification } from 'ant-design-vue'
|
||||
import { getToken } from 'utils/auth'
|
||||
import store from '@/store'
|
||||
import { getCasConfig, goLogin } from '@/store/utils'
|
||||
import { logout } from '@/services'
|
||||
|
||||
const codeMessage = {
|
||||
200: '服务器成功返回请求的数据。',
|
||||
|
@ -92,9 +94,17 @@ axiosInstance.interceptors.response.use(
|
|||
break
|
||||
case '401':
|
||||
case '509':
|
||||
store.dispatch('permission/ResetRoutes')
|
||||
break
|
||||
default:
|
||||
store.dispatch('permission/ResetRoutes', false).then(() => {
|
||||
getCasConfig().then(({ isCASLogin, casLogoutPath }) => {
|
||||
if (isCASLogin) {
|
||||
location.href = casLogoutPath
|
||||
} else {
|
||||
logout().then((res) => {
|
||||
if (res.success) goLogin()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if (!options.ignoreError) {
|
||||
notification.error({
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div class="casLogin">{{ msg }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { loginByCas } from 'services'
|
||||
import setLoginData from './tools'
|
||||
import { removeToken } from 'utils/auth'
|
||||
import { goLogin } from '@/store/utils'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
msg: '',
|
||||
url: window.location.href
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
let ticket = this.getUrlKey('ticket')
|
||||
if (!ticket || ticket == '') {
|
||||
const { redirect } = this.$route.query
|
||||
const path = redirect ? redirect.split('/#')[1] : '/sms-web/resource_dashboard'
|
||||
this.$router.replace({ path })
|
||||
return
|
||||
}
|
||||
const service = `${window.location.origin}/caslogin`
|
||||
this.login(ticket, service)
|
||||
},
|
||||
getUrlKey(name) {
|
||||
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(this.url) || ['', ''])[1].replace(/\+/g, '%20')) || null
|
||||
},
|
||||
handleLoginAfter(data) {
|
||||
setLoginData(data)
|
||||
const { redirect } = this.$route.query
|
||||
const path = redirect ? redirect.split('/#')[1] : '/sms-web/resource_dashboard'
|
||||
this.$router.replace(path)
|
||||
localStorage.removeItem('lockData')
|
||||
},
|
||||
login(ticket, service) {
|
||||
loginByCas({ ticket, service })
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.handleLoginAfter(res.data)
|
||||
this.msg = res.message
|
||||
} else {
|
||||
console.log(res.message, 'res.message')
|
||||
goLogin(true)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.msg = '登录失败'
|
||||
removeToken()
|
||||
goLogin(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -59,10 +59,10 @@ export default {
|
|||
remember: false,
|
||||
loginForm: {
|
||||
account: '',
|
||||
password: '',
|
||||
password: ''
|
||||
},
|
||||
loading: false,
|
||||
capsTooltip: false,
|
||||
capsTooltip: false
|
||||
})
|
||||
const store = useStore()
|
||||
const configs = computed(() => store.getters.pageConfig)
|
||||
|
@ -84,7 +84,7 @@ export default {
|
|||
if (state.remember) {
|
||||
const obj = {
|
||||
account: state.loginForm.account,
|
||||
password: encrypt(state.loginForm.password),
|
||||
password: encrypt(state.loginForm.password)
|
||||
}
|
||||
localStorage.setItem('cmcLoginData', JSON.stringify(obj))
|
||||
} else {
|
||||
|
@ -104,12 +104,14 @@ export default {
|
|||
const res = await login({
|
||||
account,
|
||||
password: encrypt(password),
|
||||
isManager: true,
|
||||
isManager: true
|
||||
})
|
||||
if (res.success) {
|
||||
goLogin(res.data)
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
|
@ -131,9 +133,9 @@ export default {
|
|||
configs,
|
||||
loginFormRef,
|
||||
handleLogin,
|
||||
checkCapslock,
|
||||
checkCapslock
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue