Keycloak快速上手指南,只需10分钟即可接入Spring Boot/Vue前后端分离应用实现SSO单点登录

摘要:
本文将简要介绍Keyclock的安装和使用,并举例说明如何快速访问当前流行的前端和后端分离应用程序的Keyclock。事实上,Keyclok目前有三种类型的访问:机密:适用于服务器应用程序,需要通过密钥进行浏览器登录和访问令牌获取。

登录及身份认证是现代web应用最基本的功能之一,对于企业内部的系统,多个系统往往希望有一套SSO服务对企业用户的登录及身份认证进行统一的管理,提升用户同时使用多个系统的体验,Keycloak正是为此种场景而生。本文将简明的介绍Keycloak的安装、使用,并给出目前较流行的前后端分离应用如何快速接入Keycloak的示例。

Keycloak是什么

Keycloak是一种面向现代应用和服务的开源IAM(身份识别与访问管理)解决方案

Keycloak提供了单点登录(SSO)功能,支持OpenID ConnectOAuth 2.0SAML 2.0标准协议,拥有简单易用的管理控制台,并提供对LDAP、Active Directory以及Github、Google等社交账号登录的支持,做到了非常简单的开箱即用。

Keycloak常用核心概念介绍

首先通过官方的一张图来了解下整体的核心概念

keycloak-core-concepts

这里先只介绍4个最常用的核心概念:

  1. Users: 用户,使用并需要登录系统的对象

  2. Roles: 角色,用来对用户的权限进行管理

  3. Clients: 客户端,需要接入Keycloak并被Keycloak保护的应用和服务

  4. Realms: 领域,领域管理着一批用户、证书、角色、组等,一个用户只能属于并且能登陆到一个域,域之间是互相独立隔离的, 一个域只能管理它下面所属的用户

Keycloak服务安装及配置

安装Keycloak

Keycloak安装有多种方式,这里使用Docker进行快速安装

docker run -d --name keycloak 
    -p 8080:8080 
    -e KEYCLOAK_USER=admin 
    -e KEYCLOAK_PASSWORD=admin 
    jboss/keycloak:10.0.0

访问http://localhost:8080并点击Administration Console进行登录

keycloak-web-home

创建Realm

创建一个新的realm: demo,后续所有的客户端、用户、角色等都在此realm中创建

keycloak-web-add-realm-1

keycloak-web-add-realm-2

keycloak-web-add-realm-3

创建客户端

创建前端应用客户端

创建一个新的客户端:vue-demo,Access Type选择public

keycloak-web-add-client-1

创建后端应用客户端

创建一个新的客户端:spring-boot-demo,Access Type选择bearer-only

keycloak-web-add-client-2

保存之后,会出现Credentials的Tab,记录下这里的secret,后面要用到

keycloak-web-add-client-3

关于客户端的访问类型(Access Type)

上面创建的2个客户端的访问类型分别是public、bearer-only,那么为什么分别选择这种类型,实际不同的访问类型有什么区别呢?

事实上,Keycloak目前的访问类型共有3种:

confidential:适用于服务端应用,且需要浏览器登录以及需要通过密钥获取access token的场景。典型的使用场景就是服务端渲染的web系统。

public:适用于客户端应用,且需要浏览器登录的场景。典型的使用场景就是前端web系统,包括采用vue、react实现的前端项目等。

bearer-only:适用于服务端应用,不需要浏览器登录,只允许使用bearer token请求的场景。典型的使用场景就是restful api。

创建用户和角色

创建角色

创建2个角色:ROLE_ADMIN、ROLE_CUSTOMER

keycloak-web-add-role

创建用户

创建2个用户:admin、customer

keycloak-web-add-user

绑定用户和角色

给admin用户分配角色ROLE_ADMIN

keycloak-web-add-user-role-1

给customer用户分配角色ROLE_CUSTOMER

keycloak-web-add-user-role-2

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">
    <h1>{{ msg }}</h1>
    <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登录页

keycloak-demo-1

登录admin用户

keycloak-demo-2

登录customer用户

keycloak-demo-3

总结

Keycloak部署及接入简单,轻量的同时功能又不失强大,非常适合企业内部的SSO方案。

本文示例项目地址:keycloak-demo

免责声明:文章转载自《Keycloak快速上手指南,只需10分钟即可接入Spring Boot/Vue前后端分离应用实现SSO单点登录》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle(安装PLSQL、注册、配置环境变量)C# DateTime 赋空值下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【Vuejs】269- 提升90%加载速度——vuecli下的首屏性能优化

前言 之前用 vuecli做了个博客,是一个单页面项目,大概有十个路由直接 npm run build打包出来,有一个 1M的巨大 js文件 先挂载到服务器上试试好家伙 这加载时间 仿佛过了半个世纪 首屏页面整整加载了 9s 光加载那个大文件就花了 8s这必须得做个优化了,没有用户能忍受 9s的白屏而不关闭页面的 过程中,我还顺便把项目从 vuec...

vue 数组去重

test() { const arr =[ { name: '张三', age: 22}, { name: '李四', age: 22}, { name: '张三', age:...

vue 权限管理怎么做

前言 在一个项目中,一些功能会涉及到重要的数据管理,为了确保数据的安全,我们会在项目中加入权限来限制每个用户的操作。作为前端,我们要做的是配合后端给到的权限数据,做页面上的各种各样的限制。 需求 因为这是一个工作上的业务需求,所以对于我来说主要有两个地方需要进行权限控制。 第一个是侧边菜单栏,需要控制显示与隐藏。 第二个就是页面内的各个按钮,弹窗等。 流程...

让Apache Shiro保护你的应用

https://www.ibm.com/developerworks/cn/web/wa-apacheshiro/index.html Apache Shiro 是一个框架,可用于身份验证和授权。本文提供了几个示例用来展示如何在 Java™ 应用程序中使用 Shiro 并给出了如何在一个 Grails web 应用程序中使用它的概述。为了从本文中最大限度地...

三: vue组件开发及自动化工具vue-cli

一: 组件化开发 1 组件 1: 组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能。 2: 什么是组件 而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML、cs...

vue props 用法(转载)

前面的话   组件接受的选项大部分与Vue实例一样,而选项props是组件中非常重要的一个选项。在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。本文将详细介绍Vue组件选项props 父子级组件   在介绍props之前,先介绍...