Vue应用集成Keycloak
创建vue项目
vue create vue-demo
添加官方Keycloak js适配器
npm i keycloak-js --save npm i axios --save
main.js
import Vue from 'vue' import App from './App.vue' import Keycloak from 'keycloak-js' Vue.config.productionTip = false // keycloak init options const initOptions = { url: 'http://127.0.0.1:8080/auth', realm: 'demo', clientId: 'vue-demo', onLoad:'login-required' } const keycloak = Keycloak(initOptions) keycloak.init({ onLoad: initOptions.onLoad, promiseType: 'native' }).then((authenticated) =>{ if(!authenticated) { window.location.reload(); } else { Vue.prototype.$keycloak = keycloak console.log('Authenticated') } new Vue({ render: h => h(App), }).$mount('#app') setInterval(() =>{ keycloak.updateToken(70).then((refreshed)=>{ if (refreshed) { console.log('Token refreshed'); } else { console.log('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds'); } }).catch(error => { console.log('Failed to refresh token', error) }) }, 60000) }).catch(error => { console.log('Authenticated Failed', error) })
HelloWorld.vue
<template> <div class="hello"> {{ msg }} <div> <p> current user: {{user}} </p> <p> roles: {{roles}} </p> <p> {{adminMsg}} </p> <p> {{customerMsg}} </p> </div> </div> </template> <script> import axios from 'axios' export default { name: 'HelloWorld', props: { msg: String }, data() { return { user: '', roles: [], adminMsg: '', customerMsg: '' } }, created() { this.user = this.$keycloak.idTokenParsed.preferred_username this.roles = this.$keycloak.realmAccess.roles this.getAdmin() .then(response=>{ this.adminMsg = response.data }) .catch(error => { console.log(error) }) this.getCustomer() .then(response => { this.customerMsg = response.data }) .catch(error => { console.log(error) }) }, methods: { getAdmin() { return axios({ method: 'get', url: 'http://127.0.0.1:8082/admin', headers: {'Authorization': 'Bearer ' + this.$keycloak.token} }) }, getCustomer() { return axios({ method: 'get', url: 'http://127.0.0.1:8082/customer', headers: {'Authorization': 'Bearer ' + this.$keycloak.token} }) } } } </script>
getAdmin()及getCustomer()这2个方法内部分别请求restful api
Spring Boot应用集成Keycloak
添加Keycloak Maven依赖
<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-starter</artifactId> <version>10.0.0</version> </dependency>
Spring Boot配置文件
官方文档及网上大部分示例使用的都是properties格式的配置文件,而yaml格式的配置文件相对更简洁清晰些,此示例使用yaml格式的配置文件,内容如下:
server: port: 8082 keycloak: realm: demo auth-server-url: http://127.0.0.1:8080/auth resource: spring-boot-demo ssl-required: external credentials: secret: 2d2ab498-7af9-48c0-89a3-5eec929e462b bearer-only: true use-resource-role-mappings: false cors: true security-constraints: - authRoles: - ROLE_CUSTOMER securityCollections: - name: customer patterns: - /customer - authRoles: - ROLE_ADMIN securityCollections: - name: admin patterns: - /admin
除了几个必填的配置项外,另外需要注意的几个配置项如下
- credentials.secret:上文添加客户端后Credentials Tab内对应的内容
- bearer-only:设置为true,表示此应用的Keycloak访问类型是bearer-only
- cors:设置为true表示允许跨域访问
- security-constraints:主要是针对不同的路径定义角色以达到权限管理的目的
- /customer:只允许拥有ROLE_CUSTOMER角色的用户才能访问
- /admin:只允许拥有ROLE_ADMIN角色的用户才能访问
- 未配置的路径表示公开访问
Controller内容
@RestController public class HomeController { @RequestMapping("/") public String index() { return "index"; } @RequestMapping("/customer") public String customer() { return "only customer can see"; } @RequestMapping("/admin") public String admin() { return "only admin cas see"; } }
项目效果演示
分别启动前后端项目后,本地8081端口对应vue前端项目,本地8082端口对应Spring Boot实现的restful api项目
首次访问vue前端项目
第一次访问vue项目会跳转Keycloak登录页
登录admin用户
登录customer用户
总结
Keycloak部署及接入简单,轻量的同时功能又不失强大,非常适合企业内部的SSO方案。