keycloak是开源的认证服务器,详细使用见官网:https://www.keycloak.org
安装
在开发时最方便的使用方式是在Docker下安装:
docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.0.2 start-dev
创建完成后,可以使用admin/admin登录http://localhost:8080进行下一步的操作。
可以先创建新的realm,类似于租户。然后在realm下创建用户、角色等。接下来创建client,然后用client连接认证服务器。
创建用户后,可以通过链接http://localhost:8080/realms/myrealm/account登录到账号,这里myrealm是用户所属realm。
使用脚本导入数据
安装完keycloak后,可以使用界面手工创建realm、用户和角色,也可以使用脚本导入数据。
创建一个node.js项目,引入下面的依赖项
- “@keycloak/keycloak-admin-client”: “26.0.2”,
- “keycloak-connect”: “26.0.2”
然后编写脚本1 2 3 4 5 6 7 8
| import KcAdminClient from '@keycloak/keycloak-admin-client'; import config from '../config/config.js';
const adminClient = new KcAdminClient(config.adminClient)
await adminClient.auth(config.adminClient);
export default adminClient;
|
这个脚本创建管理员权限的客户端,配置项在config中定义:1 2 3 4 5 6 7 8 9 10 11 12 13
| const baseUrl = 'http://127.0.0.1:8080';
export default { baseUrl: baseUrl, adminClient: { baseUrl: baseUrl, realmName: 'master', username: 'admin', password: 'admin', grantType: 'password', clientId: 'admin-cli' } };
|
然后编写create-realm.js:1 2 3 4 5 6
| import { readFileSync } from 'node:fs'; import adminClient from './keycloak-admin-client.js';
await adminClient.realms.create( JSON.parse(readFileSync(new URL('../config/realm-import.json', import.meta.url), 'utf8')) );
|
代码从real-import.json中读入需要创建的数据,使用adminClient.realms.create方法进行创建。
删除realm的代码如下:1 2 3
| import adminClient from './keycloak-admin-client.js';
await adminClient.realms.del({ realm : 'xlf' });
|
导入数据的json示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| { "realm": "xlf", "enabled": true, "clients": [ { "clientId": "resource-server", "enabled": true, "bearerOnly": false }, { "clientId": "spa", "enabled": true, "publicClient": true, "directAccessGrantsEnabled": true, "redirectUris": [ "http://localhost:5173/*" ] }, { "clientId": "test-cli", "enabled": true, "publicClient": true, "directAccessGrantsEnabled": true } ], "users" : [ { "username" : "user1", "enabled": true, "email" : "sys@test.org", "firstName": "user", "lastName": "user", "credentials" : [ { "type" : "password", "value" : "12345" } ], "realmRoles": [ "user", "offline_access" ], "clientRoles": { "account": [ "manage-account" ] } }], "roles" : { "realm" : [ { "name": "user", "description": "User privileges" }, { "name": "admin", "description": "Administrator privileges" } ] }
|
vue集成
首先需要安装keycloak,可以使用docker安装。然后创建realm和client。
然后创建vue3项目
npm init vue@latest。
在项目中安装keycloak.js:
npm install keycloak-js
然后,在main.js中声明keycloak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import './assets/main.css'
import { createApp } from 'vue' import App from './App.vue' import router from './router'
import Keycloak from "keycloak-js";
const keycloak = new Keycloak({ url: "http://localhost:8080", realm: "quickstart", clientId: "spa", }); window['keycloak'] = keycloak; await keycloak.init({ onLoad: "login-required" });
const app = createApp(App)
app.use(router)
app.mount('#app')
|
注意,使用window保存keycloak全局变量,这样在其它页面可以通过这个变量访问keycloak。
比如,访问用户的accesstoken:
keycloak.token
如果解析token:
keycloak.tokenParsed
还可以访问idtoken:
keycloak.idTokenParsed
使用accesstoken可以访问资源服务器。首先安装axios,然后通过axios访问资源:
1 2 3 4 5 6 7 8 9 10 11 12
| created: async function () { var keycloak = window['keycloak'] this.token = keycloak.tokenParsed const res = await axios({ url: "http://localhost:3000/secured", method: 'get', headers: { Authorization: " Bearer " + keycloak.token } })
|
接下来可以创建资源服务器。
资源服务器
可以使用keycloak创建资源服务器。首先创建node.js express项目,安装如下依赖:
app.js的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import express from 'express'; import Keycloak from 'keycloak-connect'; import cors from 'cors'
const app = express(); const port = 3000;
// Middleware configuration loaded from keycloak.json file. const keycloak = new Keycloak({});
app.use(keycloak.middleware()); app.use(cors());
app.get('/public', (req, res) => { res.json({message: 'public'}); });
app.get('/secured', keycloak.protect('realm:user'), (req, res) => { const username = req.kauth.grant.access_token.content.preferred_username; res.send(`Hello, ${username}!`); //res.json({message: 'secured'}); });
app.get('/admin', keycloak.protect('realm:admin'), (req, res) => { res.json({message: 'admin'}); });
app.use('*', (req, res) => { res.send('Not found!'); });
app.listen(port, () => { console.log(`Listening on port ${port}.`); });
|
keycloak的配置信息从keycloak.json文件中读入:
1 2 3 4 5 6 7
| { "realm": "quickstart", "bearer-only": true, "auth-server-url": "http://localhost:8080", "ssl-required": "none", "resource": "spa" }
|
注意,auth-server-url需要与访问客户端配置的认证服务一致。