首页 > 其他分享 >OpenID Connect(OIDC)认证--keycloak与springboot项目的整合

OpenID Connect(OIDC)认证--keycloak与springboot项目的整合

时间:2024-08-19 10:24:51浏览次数:14  
标签:OpenID oauth2 springboot -- spring client Spring Keycloak keycloak

OpenID Connect认证–keycloak与springboot项目的整合

文章目录

前言

在现代应用程序中,安全性是至关重要的。为了简化认证和授权流程,许多开发人员选择使用 Keycloak 作为统一的身份和访问管理解决方案。Spring Boot 是一个流行的 Java 框架,通过与 Keycloak 整合,可以轻松实现 OAuth2 和 **OpenID Connect (OIDC)**的身份认证和授权功能。本篇博客将详细介绍如何在 Spring Boot 项目中集成 Keycloak,帮助你快速搭建一个安全的 Web 应用。

什么是 Keycloak?

Keycloak 是一个开源的身份和访问管理工具,支持标准协议如 OAuth2 和 OpenID Connect。它允许开发人员轻松地将身份验证、授权和单点登录(SSO)功能集成到应用程序中。通过 Keycloak,可以管理用户、角色、权限,并将这些管理功能集中化。

关于keycloak的配置我就不在这里赘述,具体请参考博文:什么是Keycloak?怎么样使用Keycloak实现登录和权限验证?

项目配置

我将通过一个 Spring Boot 项目来演示如何集成 Keycloak。

1. 创建 Spring Boot 项目

创建一个springboot项目,并引入下面的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-spring-boot-starter</artifactId>
        <version>22.0.1</version> <!-- 根据需要选择合适的版本 -->
    </dependency>
</dependencies>

如果你使用的gradle,也大差不差:

dependencies {
   
  implementation(libs.spring.boot.starter.security)
  implementation(libs.spring.boot.starter.oauth2.client)
  implementation(libs.spring.boot.starter.oauth2.resource.server)
  implementation(libs.keycloak.spring.boot.starter)
}

主要就是上述的几个依赖,我使用的gradle来构建项目。

2. 设置 Keycloak 服务器

在整合之前,你需要设置一个 Keycloak 服务器。你可以通过 Docker 快速启动一个 Keycloak 实例:

docker run -d --name keycloak -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev

根据上述的docker容器配置,可以自己设置用户名和密码(均为admin),或者设置成你自己喜欢的方式,具体请参考博文:什么是Keycloak?怎么样使用Keycloak实现登录和权限验证?,或是查看官方文档:keycloak操作手册

由于生产需要我是将keycloak部署在公网上的,大概就是:https://keycloak.xxx.cn/,后面的链接我都用这个来替代。

3. 在 Keycloak 中创建 Realm 和 Client

登录到 Keycloak 管理控制台后:

  1. 创建 Realm: 在左侧菜单中选择 “Add realm”,输入一个名称,例如 myrealm,然后点击 “Create”。

  2. 创建 Client
    在创建好的 Realm 中,导航到 “Clients” 部分,点击 “Create” 创建一个新客户端。
    • Client ID: 输入一个客户端 ID,例如 spring-boot-client
    • Client Protocol: 选择 openid-connect
    • Root URL: 输入 Spring Boot 应用的根 URL,例如 http://localhost:8081
    • Save: 点击 “Save” 保存配置。

在客户端的配置页面,确保 “Access Type” 设置为 confidential 并保存,然后生成并复制客户端的 Secret

上述的信息在后续在配置springboot后端的时候会用到。这部分在这篇博文上也有提到:什么是Keycloak?怎么样使用Keycloak实现登录和权限验证?

4. 配置 Spring Boot 应用

application.ymlapplication.properties 中,添加 Keycloak 配置信息:

spring:
  application:
    name: customer_management
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: web_app
            authorization-grant-type: implicit
            scope:
              - openid
        provider:
          keycloak:
            issuer-uri: https://keycloak.scysn.cn/realms/test
            user-name-attribute: preferred_username
      resource server:
        jwt:
          issuer-uri: https://keycloak.scysn.cn/realms/test
server:
  port: 8081
application:
  security:
    oauth2:
      audience: account,api://default
  oauth2:
    # authorization-url: http://localhost:9080/realms/ysn/protocol/openid-connect/auth
    authorization-url: https://keycloak.scysn.cn/realms/test/protocol/openid-connect/auth

在上述的配置文件中,主要需要配置的就是下面这几个参数:

spring.security.oauth2.client.registration.keycloak.client-id=login-app
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/realms/SpringBootKeycloak
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/SpringBootKeycloak
5. 配置 Spring Security

在 Spring Boot 项目中,通过创建一个 SecurityConfig 类来配置安全性:

在这个配置类中主要是配置以下这个bean对象:

@Bean
public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception {
   
    http.authorizeHttpRequests(auth -> auth
       .requestMatchers(new AntPathRequestMatcher("/customers*", HttpMethod.OPTIONS.name()))
       .permitAll()
       .requestMatchers(new AntPathRequestMatcher("/customers*"))
       .hasRole("user")
       .requestMatchers(new AntPathRequestMatcher("/"))
       .permitAll()
       .anyRequest()
       .authenticated());
    http.oauth2ResourceServer((oauth2) -> oauth2
       .jwt(Customizer.withDefaults()));
    http.oauth2Login(Customizer.withDefaults())
       .logout(logout -> logout.addLogoutHandler(keycloakLogoutHandler).logoutSuccessUrl("/"));
    return http.build();
}

在上面的代码中,oauth2Login *()方法将**OAuth2LoginAuthenticationFilter*添加到过滤器链中。该过滤器拦截请求并应用 OAuth 2 身份验证所需的逻辑oauth2ResourceServer方法验证 JWT 令牌与 Keycloak 服务器的绑定。它还强制执行前面讨论的约束。

Keycloak 返回一个包含所有相关信息的令牌。为了使 Spring Security 能够根据用户分配的角色做出决策,我们必须解析令牌并提取相关详细信息。但是 Spring Security 通常在每个角色名称中添加*“ROLES_”前缀,而 Keycloak 则发送纯角色名称。为了解决这个问题,我们创建了一个辅助方法,它为从 Keycloak 检索到的每个角色添加“ROLE_”前缀。*

@Bean
Collection generateAuthoritiesFromClaim(Collection roles) {
   
    return roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(
           Collectors.toList());
}

现在我们可以继续解析令牌了。首先,我们必须检查令牌是否是 OidcUserAuthority 或 OAuth2UserAuthority 的实例。由于 Keycloak 令牌可以是任何一种类型,因此我们需要实现解析逻辑。下面的代码检查令牌的类型并决定解析机制。

boolean isOidc = authority instanceof OidcUserAuthority;
    if (isOidc) {
    
       /// Parsing code here
    }

默认情况下,令牌是 OidcUserAuthority 的一个实例。

如果令牌是 OidcUserAuthority 实例,则可以将其配置为包含两个组或领域访问下的角色。因此,我们必须检查两者以提取角色,如下面的代码所示,

if (userInfo.hasClaim(REALM_ACCESS_CLAIM)) {
   
    var realmAccess = userInfo.getClaimAsMap(REALM_ACCESS_CLAIM);
    var roles = (Collection) realmAccess.get(ROLES_CLAIM);
    mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
} else if (userInfo.hasClaim(GROUPS)) {
   
    Collection roles = (Collection) userInfo.getClaim(GROUPS);
    mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
}

但是,如果令牌是 OAuth2UserAuthority 实例,我们需要按如下方式解析它:

var oauth2UserAuthority = (OAuth2UserAuthority) authority;
Map<String, Object> userAttributes 

标签:OpenID,oauth2,springboot,--,spring,client,Spring,Keycloak,keycloak
From: https://blog.csdn.net/m0_63144319/article/details/141316273

相关文章

  • windows系统安装pygraphviz失败解决
    当使用到图形化包时,需要引入pygraphviz库,`pipinstallgraphviz`报错building'pygraphviz._graphviz'extensioncreatingbuild\temp.win-amd64-cpython-311pygraphviz/graphviz_wrap.c(9):warningC4005:“SWIG_PYTHON_STRICT_BYTE_CHAR”:宏重定义pygraphviz/gra......
  • 环境多介质逸度模型实践技术与典型案例【代码】应用
    随着污染物在各种环境中的迁移和转化,多介质污染物模型日益受到关注。在各类多介质模型中,基于逸度概念的逸度模型由于运用范围广,建模数据要求较低而广受欢迎。帮助广大科研及工程人员能够正确运用逸度模型评估有机污染物的危害。专题一:基本理论1.逸度的定义2.逸度模型的基本......
  • 分布式锁的实现方案
    分布式锁是分布式系统中用于确保多个进程或服务在访问共享资源时能够保持互斥,以避免发生数据冲突或不一致性问题的一种同步机制。与传统的锁机制相比,分布式锁是为了解决跨多个计算节点的资源同步问题。在分布式环境下,资源可能被分布在不同的服务器上,这就需要一种跨服务器的锁机......
  • 北斗/GNSS高精度数据处理暨GAMIT/GLOBK v10.75软件
    随着GNSS导航定位技术在不同领域的广泛应用和技术更新的飞速发展,在大型工程项目的设计、施工、运行和管理各个阶段对工程测量提出了更高的要求,许多测绘、勘测、规划、市政、交通、铁道、水利水电、建筑、矿山、道桥、国土资源、气象、地震等行业部门在大型工程建设过程中需应用......
  • 智能小程序 Ray 开发面板 SDK —— 工具方法中时间和转换 SDK 汇总
    时间本文介绍了时间相关工具。秒转时分秒数组名称parseSecond描述将一个基于秒的数转化成固定长度为2的多个字符串。请求参数参数数据类型说明是否必填secondnumber基于秒的数是numnumber字符串长度固定,默认值为2否返回参数参数数据类型说明resultstring个项都是......
  • java队列
    1.队列定义:在Java中,队列(Queue)是一种常用的数据结构,属于java.util包。Queue接口继承自Collection接口,定义了一些基本操作,如入队、出队、查看队列头部等。Java提供了多种实现Queue接口的类,这些类可以满足不同的使用需求。2.Java队列的常见实现LinkedList:实现了Que......
  • 秒开WebView?Android性能优化全攻略
    在如今的移动应用时代,用户体验的好坏直接关系到应用的成功与否。而在众多的用户体验因素中,应用的加载速度尤其重要。特别是对于使用 WebView 加载网页的应用,如果加载速度过慢,用户往往会产生不满,从而流失。因此,实现“秒开”WebView成为了开发者必须面对的一项挑战。本文将深......
  • 30种常见的GIS矢量数据格式
    还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,echarts等技术开发,欢迎加底部微信(gis-dajianshi),一起交流。No.内容链接1Openlayers【入门教程】-......
  • 掌握 RSS 源生成秘籍,‌轻松打造个性化信息流!‌
    500.其他生成RSS源的方法除了RSSHub,也有很多方法可以生成RSS源,当然会更复杂一点。其实通过之前几篇博客,基本上已经够用了,本篇文章仅仅是简单介绍一些方法,不会太过深入(因为我也没弄过......
  • 解锁强强组合: 使用 Kafka + ClickHouse 快速搭建流数据实时处理平台(DoubleCloud 博
    我们想要解决的问题让我们深入一个现实场景:设想你负责汇总多个销售点系统产生的大量数据。这些数据需要被实时处理并在高级分析仪表板上展示,以提供全面的洞察。在数据处理领域,速度至关重要。ClickHouse作为速度之王,它从不减速且异常迅速。其在并发处理方面的高效性以及成本效......