杂记 | 使用keycloak实现SSO单点登录(新手向,概念、原理、逻辑、详细步骤、难点解释)


之前几篇有关keycloak的文章:

keycloak的介绍和基本概念

Linux服务器使用docker安装keycloak(docker-compose)

使用Docker快速上手Keycloak(官方文档翻译)

01 单点登录的概念

先用案例说明:

假设有一个大型企业,该企业使用了多个内部应用程序和服务,包括员工门户、邮箱、人力资源系统、财务系统等。在没有单点登录的情况下,每个应用程序都需要员工单独登录,这会导致以下问题:

  1. 用户体验糟糕:员工需要记住多个不同的用户名和密码,并且在每次登录时都需要输入这些凭据,这增加了用户的负担和登录过程的时间。

  2. 安全性问题:如果员工为了方便而使用相同或类似的密码,一旦其中一个应用程序被攻破,攻击者可能会访问到其他应用程序,因为相同的凭据可在所有应用程序上使用。

  3. 密码管理困难:员工可能会频繁地忘记密码,导致需要重置密码的请求增多,增加了IT部门的工作量。

而单点登录技术就是为了解决这些问题而出现的。

概念
单点登录(Single Sign-On,简称SSO)是一种身份验证和授权机制,允许用户在多个应用程或服务之间使用同一组凭据(例如用户名和密码)进行登录,而不需要在每个应用程序中都输入凭据。使用SSO,用户只需要在一次登录后,即可访问连接到SSO系统的所有其他应用程序,简化了用户体验,提高了安全性,并减少了密码管理的负担。

上述案例中,实施单点登录后,员工只需在第一次访问其中一个应用程序时输入其用户名和密码。之后,当员工访问连接到SSO系统的其他应用程序时,无需再次输入凭据。解决了分别登录出现的问题。

02 keycloak的中的相关概念

2.1 概念之间的关系

在我之前的文章中,介绍了keycloak中核心的一些概念。

在此,我用思维导图的方式将这些概念进行整合:

在这里插入图片描述

  • keycloak
    实现身份与访问的一整套解决方案。具体而言,它是搭建在某台服务器上的一个服务实例,可以通过管理控制台进行管理和配置。

  • realm 领域
    领域是keycloak中专门用来管理项目的工作区,每个Keycloak实例可以包含一个或多个领域,每个领域是一个独立的安全域,不同领域之间的资源相互隔离。领域分为两类,一类是master领域,由Keycloak刚启动时创建,用于管理admin账号以及创建其他的领域;另一类是用户自己创建的普通领域,用于管理具体的项目和用户。

  • client 客户端
    客户端在领域中创建,一个领域可以创建多个客户端,例如一个企业可以创建两个客户端:销售人员客户端、研发人员客户端。在具体的客户端中管理具体的应用程序。

  • application 应用程序
    一个客户端可以配置一至多个应用程序,同一客户端下的多个应用程序可以实现单点登录。一个应用程序可以是SpringBoot应用、JavaScript应用、Android应用等。

  • adapter 适配器
    适配器,用来实现客户端与Keycloak之间的集成。具体而言,同一客户端下的应用共用一个客户端适配器的配置,这也确保了单点登录的实现。

2.2 案例说明

如果对这些概念的关系还是比较生疏,下面通过一个例子进行说明:

假设有一家大型公司,使用keycloak管理用户身份服务,公司系统中的使用者分为客户和员工两大类。系统中有许多应用,则可能的配置如下:
在这里插入图片描述
在这个公司系统中,有三个领域,分别是:master、consumer、employee,在employee领域下,存在两个客户端,分别是前台销售客户端和后台管理客户端。

前台销售客户端面向前台销售人员使用,其下有3个应用程序,这三个应用程序可能是使用不同的框架实现的,例如一个使用SpringBoot搭建,另一个使用Node.js。

这3个应用程序有各自的适配器,但每个适配器配置的内容都适配到“前台销售”这个客户端,这样个应用程序就可以实现单点登录了。

关于适配器中配置的具体内容,接下来会提到。

03 如何使用keycloak实现单点登录

3.1 步骤与效果说明

因为仅作为演示,会尽量排除与单点登录无关的配置和操作,集中理解单点登录需要的操作。

步骤:

  1. 搭建keycloak服务
  2. 创建一个领域
  3. 创建一个客户端
  4. 创建一个用户
  5. 创建两个应用并配置适配器

要实现的效果:
登录其中一个客户端后,另一个客户端不用登录也可访问。

3.2 环境说明

本次演示使用2台主机,一台是云服务器,另一台是本地主机,keycloak部署在云服务器,两个应用分别部署在本地和云服务器。
作为学习,也可所有服务与应用都部署在本地。

04 操作步骤

4.1 在服务器上创建并启动keycloak服务

详见:Linux服务器使用docker安装keycloak(docker-compose)

4.2 创建一个领域

在这里插入图片描述
在这里插入图片描述

4.3 创建一个客户端

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.4 获取客户端适配器配置

所有使用该配置的应用被视为属于这一客户端
在这里插入图片描述
点击Download adapter config
在这里插入图片描述
在这里插入图片描述
下载或记住这一客户端的配置,之后创建应用时使用。

4.5 创建一个用户

在这里插入图片描述
给用户设置一个密码
在这里插入图片描述

4.6 创建第一个应用

创建第一个应用,名为keycloak_sso_local。
在这里插入图片描述
编辑pom.xml文件
在这里插入图片描述
加入依赖配置

<dependencies>
    ...
    <!--keycloak-->
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

<!--keycloak-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.keycloak.bom</groupId>
            <artifactId>keycloak-adapter-bom</artifactId>
            <version>21.1.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

编写controller

@RestController
public class LocalController {
    
    
   @GetMapping("/")
   public String withoutLogin() {
    
    
       return "未登录可以看到此页面";
   }
   @GetMapping("/local")
   public String login() {
    
    
       return "您已登录local应用";
   }    
}

编写application.yml

# 以下配置参考刚才下载的adapter配置(本文4.4部分)
keycloak:
  realm: myrealm
  auth-server-url: https://xxx.xxx.xxx.xxx:8443/
  ssl-required: external
  resource: myclient
  public-client: true
  confidential-port: 0
  # 设置以下资源需要登录才能访问
  security-constraints:
    - auth-roles:
        - default-roles-myrealm # 用户创建后的默认角色
      security-collections:
        - patterns:
            - /local/*

编写好后,在本地启动该应用,测试能否访问:
浏览器地址栏输入http://localhost:8080
在这里插入图片描述
然后再输入要访问的资源链接http://localhost:8080/local,此时会重定向到登录页面
在这里插入图片描述
在这里插入图片描述
跳转到的登录页面的地址是keycloak服务所在的服务器ip/域名。
输入刚才创建的用户名(myuser)和密码,点击登录,登录成功后重定向回localhost(创建领域时配置过)
可以成功访问到http://localhost:8080/local
在这里插入图片描述

4.7 创建第二个应用

第一个应用创建成功并能正常运行和访问,接下创建第二个应用。
创建步骤和第一个应用一致,不同的地方:

  • 应用名设置为keycloak_sso_remote。(便于区分)
  • Controller中第二个接口改为
    @GetMapping("/remote")
    public String login() {
          
          
        return "您已登录remote应用";
    }    
    
  • application.yml文件
keycloak:
  realm: myrealm
  auth-server-url: https://xxx.xxx.xxx.xxx:8443/
  ssl-required: none			# 改成了none
  resource: myclient
  public-client: true
  confidential-port: 0
  # 设置以下资源需要登录才能访问
  security-constraints:
    - auth-roles:
        - default-roles-myrealm # 用户创建后的默认角色
      security-collections:
        - patterns:
            - /remote/*			# 改成了remote

创建好后,将第二个应用上传到服务器并启动,测试可访问性。

4.8 单点登录测试

首先在本地和服务器同时启动服务。
然后在本地主机上打开浏览器,分别开启两个窗口,输入对应地址。
在这里插入图片描述
接着,在左侧的浏览器地址栏输入路径http://localhost:8080/local,进行登录。
登录成功后,右侧输入地址http://ip:8080/remote
在非单点的情况下,左侧和右侧需要分别登录,我们成功配置了单点登录,左侧登录成功后,右侧就可以直接访问了,不需要再次登录。
在这里插入图片描述
(先右后左同理)

05 回顾与说明

5.1 关于adapter配置文件

在keycloak控制台的某一具体客户端右上角导出的配置文件,记录了该客户端基本的信息,最重要的信息有3个:

  • auth-server-url 认证服务地址
  • realm 领域名称
  • resource 客户端名称

这三项信息唯一确定了一个客户端,因此,如果2个应用的适配器配置中这三项的配置相同,那么这2个应用就属于同一客户端下的应用,这2个应用之间也就可以实现单点登录。

在SpringBoot项目中,application.yml中关于keycloak的配置,即为应用适配器在SpringBoot应用中的的具体形式,在其他应用中可能是其他形式。

5.2 关于重定向地址

在创建客户端时,设置了2个重定向地址:
在这里插入图片描述
这两个地址是在何处起了什么作用?
当一个请求访问本地应用的某个资源(例如/local这个资源),因为在适配器(application.yml)中配置了该资源需要登录才能访问,而该请求未登录,此时应用会跳转到keycloak的登录页面(适配器中配置了auth-server-url,应用会通过该配置获取客户端上的详细配置,记载了要跳转的登录页面在哪里),登录成功后,会跳转到某个地址,这里的跳转地址就是我们设置的重定向地址。

5.3 关于报错PKIX path building failed

如果部署keycloak服务的服务器使用了https,但没有可信的https证书,则会出现该错误,解决方法参考我的另一篇:报错 | PKIX path building failed: …SunCertPathBuilderException:unable to find valid certification…

最好是使用有可信证书的https和域名访问,可以避免许多麻烦。

猜你喜欢

转载自blog.csdn.net/xuzhongyi103/article/details/131525379