刚开始使用keycloak的时候,很多接口参数不知道,就感觉你访问任何页面都需要登录才可访问。但项目需要某些页面不需要用户登录也可以查看。我通过Protected urls #2 | github issue受到了启发。
keycloak中的init.onLoad
可选两个参数login-required
、check-sso
。其中,login-required
会检查你是否登录到了keycloak以及判断你登录的客户端是否正确,如果没有登录就跳转到keycloak的登录页面;check-sso
只会判断你登录的客户端是否正确,如果没有登录就会保持未登录的状态。
所以check-sso
是我所需要的。
我是使用vue开发的项目,用的插件是@dsb-norge/vue-keycloak-js | npm。以下内容均是基于这个插件的。
初始化设置
最开始的开始,当然是安装插件了,这块就不需要我多说了,建议用cnpm安装,这个比较快。
在main.js文件里,添加使用vue-keycloak-js代码。
用token不需要另外保存到localStorage了,只需要通过this.$keycloak.token获取即可。
import VueKeyCloak from '@dsb-norge/vue-keycloak-js' Vue.use(VueKeyCloak, { init: { onLoad: 'check-sso' }, config: { url: process.env.VUE_APP_AUTH_URL, realm: process.env.VUE_APP_AUTH_REALM, clientId: process.env.VUE_APP_AUTH_CLIENT_ID, }, onReady: kc => {
if(kc.authenticated){ http.get('_users/' + kc.subject) .then((response) => { store.commit('auth/SET_CURRENT_USER', response.data.data) }) .catch((error) => { console.log(error) }) } new Vue({ router, store, created () { this.$watch('$keycloak.userInfo', function () {
if(kc.authenticated){
http.get('_users/' + kc.subject) .then((response) => { store.commit('auth/SET_CURRENT_USER', response.data.data) }) .catch((error) => { console.log(error) }) }
}, { immediate: true })
}, render: h => h(App) }).$mount('#app') } })
|
路由设置
routes.js
export default [ { path: '/', name: 'main', component: Main }, { path: '/secured', name: 'secured', component: Secured, meta: { requiresAuth: true } } ]
|
router.js
router.beforeEach((routeTo, routeFrom, next) => {
const authRequired = routeTo.matched.some((route) => route.meta.authRequired)
if (!authRequired) return next()
if (Vue.prototype.$keycloak.authenticated) {
if (Vue.prototype.$keycloak.hasRealmRole('C_ADMIN')) return next()
if (userRoutes.some(route => route.path === routeTo.path)) return next()
next({ path: userRoutes[0].path })
} else { const loginUrl = Vue.prototype.$keycloak.createLoginUrl() window.location.replace(loginUrl)
}
})
|
主页跳转问题
后来我发现这样设置,出现了一点点小问题。
如果你退出账户时,不在首页,则重新登录就直接跳转到你原来所在的页面。
这个问题看起来没有太大的毛病,但是如果是普通用户和管理员用户之间切换,那么管理员状态登录就无法直接进入主页。
这个问题我尝试了很多种方法:
- 删除路由历史记录(其实这个不是问题的根本,所以这么做是无意义的,况且Vue Router不存在清空历史记录的函数和功能)
- 尝试从刚进入页面时进行全局路由设置,会导致next()循环
- 通过退出用户,设置跳转主页,可实现管理员下次系统进入主页,但无法实现普通用户切换管理员进入非主页问题
最后的解决方法是,单独对每一个路由进行设置,如果是初次进入系统,进入页面如果不是主页就跳转到主页。以我的某个页面为例:
const containersRoutes = [ { path: '/containerList', name: '容器列表', icon: 'box', component: () => lazyLoadView(import('@views/docker-hub/containerList')), meta: {
authRequired: true, beforeResolve(routeTo, routeFrom, next) {
if (routeFrom.name !== null) return next() if(Vue.prototype.$keycloak.hasRealmRole('C_ADMIN')) return next('/') return next('/imageList')
},
}, props: (route) => ({ user: store.state.auth.currentUser || {} }) } ]
|
参考链接
Vue集成Keycloak | 简书
Protected urls #2 | github issue
@dsb-norge/vue-keycloak-js | npm
写文不易,如需转载,请注明出处。
注意文章编写时间,一切以官方文档为主。
如果某处写的有问题,欢迎发邮件,一起交流讨论,共同进步。