diff --git a/src/App.vue b/src/App.vue index 52b6dd6..d90aec4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -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) }) + + + diff --git a/src/permission.js b/src/permission.js index 2215e66..21abf35 100644 --- a/src/permission.js +++ b/src/permission.js @@ -1,52 +1,81 @@ -/** - * Created by HaijunZhang on 2018/11/12. - */ -import store from './store' -import router from './router' -import { getToken, setToken } from 'utils/auth' -import { getQuery } from 'utils' -import { isEmpty, assign } from 'lodash-es' - -const { token } = getQuery(location.hash) -if (token) { - setToken(token) -} - -const whiteList = ['/login', '/404', '/401', '/license', '/sso'] -router.beforeEach(async (to, from, next) => { - if (isEmpty(history.state.current)) { - assign(history.state, { current: from.fullPath }) - } - if (getToken()) { - // 判断用户是否处于登录状态 - if (to.path === '/login') { - // 如果已经登录重定向到主页 - await store.dispatch('permission/ResetRoutes', false) - next('/login') - } else { - // 为null的场景: 刷新页面或者新开窗口; - const addRoutes = store.getters.addRoutes - if (addRoutes) { - next() - } else { - try { - await store.dispatch('permission/GenerateRoutes') - store.dispatch('GetUserInfo') - next({ ...to, replace: true }) - } catch (error) { - // remove token and go to login page to re-login - await store.dispatch('permission/ResetRoutes', false) - next('/login') - } - } - } - } else { - // 用户没有登录 - if (whiteList.includes(to.path)) { - // 在白名单里直接跳转 - next() - } else { - next('/login') - } - } -}) +/** + * Created by HaijunZhang on 2018/11/12. + */ +import store from './store' +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', '/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' || to.path === '/caslogin') { + // 如果已经登录重定向到主页 + await store.dispatch('permission/ResetRoutes', false) + const { isCASLogin, casLoginPath } = await getCasConfig() + if (!isCASLogin) { + next('/login') + } else { + redirectToCasLogin(to, next, ticket, casLoginPath) + } + } else { + // 为null的场景: 刷新页面或者新开窗口; + const addRoutes = store.getters.addRoutes + if (addRoutes) { + next() + } else { + try { + await store.dispatch('permission/GenerateRoutes') + store.dispatch('GetUserInfo') + next({ ...to, replace: true }) + } catch (error) { + // remove token and go to login page to re-login + await store.dispatch('permission/ResetRoutes', false) + const { isCASLogin, casLoginPath } = await getCasConfig() + if (!isCASLogin) { + next('/login') + } else { + redirectToCasLogin(to, next, ticket, casLoginPath) + } + } + } + } + } else { + // 用户没有登录 + if (whiteList.includes(to.path)) { + // 在白名单里直接跳转 + const { isCASLogin, casLoginPath } = await getCasConfig() + if (!isCASLogin) { + next() + } else { + redirectToCasLogin(to, next, ticket, casLoginPath) + } + } else { + goLogin() + } + } +}) diff --git a/src/router/constant.ts b/src/router/constant.ts index c85eeeb..de8ac26 100644 --- a/src/router/constant.ts +++ b/src/router/constant.ts @@ -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', diff --git a/src/services/index.js b/src/services/index.js index 65d9069..c226e48 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -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) } diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js index 208d1d0..b900432 100644 --- a/src/store/modules/permission.js +++ b/src/store/modules/permission.js @@ -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() }) } diff --git a/src/store/utils.js b/src/store/utils.js index 7b3dc0c..bcf8a35 100644 --- a/src/store/utils.js +++ b/src/store/utils.js @@ -1,14 +1,45 @@ -export const setBrowser = (icon, title) => { - const head = document.getElementsByTagName('head')[0] - const linkTag = document.createElement('link') - linkTag.href = icon - linkTag.setAttribute('rel', 'shortcut icon') - linkTag.setAttribute('type', 'image/x-icon') - head.appendChild(linkTag) - document.title = title -} -// /system/configs/page -> [ '/system','/system/configs','/system/configs/page'] -export const urlToList = (url) => { - const urllist = url.split('/').filter((i) => i) - return urllist.map((urlItem, index) => `/${urllist.slice(0, index + 1).join('/')}`) -} +import { getSystemConfigs } from 'services' +import store from '@/store' +export const setBrowser = (icon, title) => { + const head = document.getElementsByTagName('head')[0] + const linkTag = document.createElement('link') + linkTag.href = icon + linkTag.setAttribute('rel', 'shortcut icon') + linkTag.setAttribute('type', 'image/x-icon') + head.appendChild(linkTag) + document.title = title +} +// /system/configs/page -> [ '/system','/system/configs','/system/configs/page'] +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 +} diff --git a/src/utils/request.js b/src/utils/request.js index 059a5a4..880a3f7 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -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({ diff --git a/src/views/login/casLogin.vue b/src/views/login/casLogin.vue new file mode 100644 index 0000000..7e57a19 --- /dev/null +++ b/src/views/login/casLogin.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/views/login/login.vue b/src/views/login/userLogin.vue similarity index 97% rename from src/views/login/login.vue rename to src/views/login/userLogin.vue index 24d9d2e..17dcf4c 100644 --- a/src/views/login/login.vue +++ b/src/views/login/userLogin.vue @@ -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 } - }, + } }