网站首页 > 编程文章 正文
Keycloak Client Adapters简介
Keycloak client adapters are libraries that make it very easy to
secure applications and services with Keycloak. We call them adapters
rather than libraries as they provide a tight integration to the
underlying platform and framework. This makes our adapters easy to use
and they require less boilerplate code than what is typically required
by a library
以上是Keycloak管网对Client Adapter的解释。简单理解就是,Keycloak为不同平台的应用提供了一些库,方便应用集成Keycloak服务。
对于使用OpenID Connector协议,Keycloak针对不同平台的应用,提供了如下adapter:
Java
- JBoss EAP
- WildFly
- Fuse
- Tomcat
- Jetty 9
- Servlet Filter
- Spring Boot
- Spring Security
JavaScript (client-side)
- JavaScript
Node.js (server-side)
- Node.js
C#
- OWIN (community)
Python
- oidc (generic)
Android
- AppAuth (generic)
iOS
- AppAuth (generic)
Apache HTTP Server
- mod_auth_openidc
这里主要关注Java相关的adapter使用。首先介绍使用比较简单、通用的Servlet Filter Adapter,并通过源码分析Servlet Filter Adapter的原理、流程,后续再介绍如何使用Spring Boot Adapter以及Spring Security Adapter
使用Servlet Filter Adapter实现Token校验
背景简介
有一个应用,提供了REST API,但是需要提供合法的Token,Token校验通过了才能访问
环境准备
1.在Keycloak中创建测试Realm,名称为SpringBoot
2.创建Access Type为public类型的Client,client id为adapter-servlet-public,用于模拟前端应用获取Token,如下:
3.创建Acess Type为bearer-only类型的Client,client id为adapter-servlet-bearer,对应后端应用,如下:
从Installation Tab页面获取adapter-servlet-bearer配置信息,如下:
{
"realm": "SpringBoot",
"bearer-only": true,
"auth-server-url": "http://localhost:8180/auth/",
"ssl-required": "external",
"resource": "adapter-servlet-bearer",
"confidential-port": 0
}
4.在Keycloak管理控制台创建用户zhangsan,密码为123456
以上相关信息的创建可以参考前文Keycloak管理控制台操作
应用开发
1.创建SpringBoot应用
在父pom中指定SpringBoot版本及keycloak版本,如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot.version>2.5.5</spring-boot.version>
<keycloak.version>16.0.0</keycloak.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.创建keycloak-adapter-servlet子模块
创建一个子模块,并添加Keycloak Servlet Filter Client Adapter依赖和spring-boot-web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>${keycloak.version}</version>
</dependency>
添加application.yml配置,指定服务端口及日志级别
server:
port: 8081
logging:
level:
org.keycloak: debug
3.创建REST 资源
package com.ywu.keycloak.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ResourceController {
@ResponseBody
@RequestMapping("/protected/resource")
public String protectedResource() {
return "this is protected resource";
}
@ResponseBody
@RequestMapping("/common/resource")
public String commonResource() {
return "this is common resource";
}
}
其中,/protected/resource表示受保护的资源,需要验证后才能访问;/common/resource表示能随意访问
4.创建Keycloak配置
在resources目录下新建keycloak目录,并在keycloak目录下创建keycloak-bearer-only.json文件,内容为前文创建的bearer-only类型client的Installation信息,如下:
{
"realm": "SpringBoot",
"bearer-only": true,
"auth-server-url": "http://localhost:8180/auth/",
"ssl-required": "external",
"resource": "adapter-servlet-bearer",
"confidential-port": 0
}
5.配置Keycloak Servlet Filter
package com.ywu.keycloak.config;
import org.keycloak.adapters.servlet.KeycloakOIDCFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class FilterConfig {
/**
* 配置keycloak servlet adapter 过滤器
* @return
*/
@Bean
public FilterRegistrationBean<KeycloakOIDCFilter> keycloakOIDCFilter() {
FilterRegistrationBean<KeycloakOIDCFilter> keycloakOIDCFilter = new FilterRegistrationBean<>();
keycloakOIDCFilter.setFilter(new KeycloakOIDCFilter());
// 添加过滤器拦截的URL,即访问这些URL需要认证收授权
keycloakOIDCFilter.addUrlPatterns("/protected/*");
// 为过滤器设置keycloak json配置文件的路径
Map<String, String> initParams = new HashMap<>();
String configFileName = "keycloak-bearer-only.json";
String keycloakJsonFilePath = getKeycloakJsonFilePath(configFileName);
initParams.put(KeycloakOIDCFilter.CONFIG_FILE_PARAM, keycloakJsonFilePath);
keycloakOIDCFilter.setInitParameters(initParams);
return keycloakOIDCFilter;
}
/**
* 获取resources目录下keycloak json配置文件的绝对路径
*
* @param fileName
* @return
*/
private String getKeycloakJsonFilePath(String fileName) {
URL resource = FilterConfig.class.getResource(String.join(File.separator, "/keycloak", fileName));
return resource.getPath();
}
}
通过FilterRegistrationBean注册了一个KeycloakOIDCFilter,拦截/protected/*模式匹配的资源,指定了Filter使用的Keycloak配置为keycloak-bearer-only.json
到此,整个应用就开发完毕了
测试
启动测试服务,正常情况下,服务会监听在8081端口
直接访问
通过Post Man访问common resource
可以正常访问
使用Post Man访问受保护资源,如下:
返回401,表示未授权
获取Token
使用之前创建的public类型的client来获取Token,模拟前端请求Token,如下:
其中,获取Token的URL格式为http://{keycloak服务器域名}:{keycloak服务器端口}/auth/realms/{自定义realm名称}/protocol/openid-connect/token
cURL格式的请求如下:
curl --location --request POST 'http://localhost:8180/auth/realms/SpringBoot/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: JSESSIONID=6FCFD67D3063CFE0A443BD7B161601A5.f64bbac2c4cd; JSESSIONID=6FCFD67D3063CFE0A443BD7B161601A5' \
--data-urlencode 'client_id=adapter-servlet-public' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=zhangsan' \
--data-urlencode 'password=123456'
正常情况下就能获取到Token,可以看出Token是JWT,并且默认有效期只要300秒
通过Token访问受保护资源
重新访问受保护资源,这次在请求Header中携带上Token,如下:
这次请求添加了请求头Authorization,值为Bearer {Token},其中Token部分即为上一步获取的JWT
cURL格式请求如下:
curl --location --request GET 'http://localhost:8081/protected/resource' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJyOGxFQUMyQmZSVUhUVDUtRGEyUUp3dFJBNFdMbnpOaHZsTjdMSVF1YXVZIn0.eyJleHAiOjE2NTAyOTA1ODUsImlhdCI6MTY1MDI5MDI4NSwianRpIjoiY2JiMmZjOTYtNGNhNi00YjI2LTkzMGItMmQ2MzczZmUyZTFhIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgwL2F1dGgvcmVhbG1zL1NwcmluZ0Jvb3QiLCJhdWQiOlsiYWRhcHRlci1zZXJ2bGV0IiwiYWNjb3VudCJdLCJzdWIiOiI5MjUzNmM2Ny00YzdlLTQ2YzctOWM0NS04YWRkYWVjYTRmYzQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZGFwdGVyLXNlcnZsZXQtcHVibGljIiwic2Vzc2lvbl9zdGF0ZSI6IjQ0NmRmYTJmLTZkOGEtNDU0Mi05YmRhLWZmODU4ZjQxYzVhMSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJBRE1JTiIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWRhcHRlci1zZXJ2bGV0Ijp7InJvbGVzIjpbIlNZUyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ6aGFuZ3NhbiJ9.o7nnY_ZqCCJYy_bXQFgx99PKrX0ZH9k6v3JzHDFkpzsHL9nEyZu68EDJyts04DGb58gkHyMgcULu6YoN2KJ48jwmMwiM4yfXfSGR6lrKPfWxBpmMYeB1kxgU69eCwxNdVfIGC49Ilt6kwVTI7GZinwxJNfWZrOUpgXqpMvajd0MsB4PVCZS46cN5qh9AH-RAvbEkMKoa3mV_lTe7QZ5VqKk45ztS2gP5SUYNygMhgT6TXuHBQRTSMAcALEvyIjNmKNuPX4SNwReLk3DrmpA3gcHEQG8uyRTT5LZXchS71egr7QAXNIwBnrUg-pDPsa-Un-pJHbjJ1xJZmNU1H-Ihjw' \
--header 'Cookie: JSESSIONID=6FCFD67D3063CFE0A443BD7B161601A5'
可以看出,这次能正常访问受保护资源了
使用Servlet Filter Adapter实现登录授权认证
背景简介
有些应用需要用户授权登录才能访问,此时可以使用授权码流程,当用户登录到应用时,发现未登录,则重定向到Keycloak服务并登陆,再重定向回应用
环境准备
- 创建Access Type类型为confidential的Client,client id为adapter-servlet-credentials-1,添加Valid Redirect URIs为http://localhost:8081/protected/*,获取其Installation信息,如下:
{
"realm": "SpringBoot",
"auth-server-url": "http://localhost:8180/auth/",
"ssl-required": "external",
"resource": "adapter-servlet-credentials-1",
"credentials": {
"secret": "0e053b89-d87f-460a-92ec-adcd11ce6034"
},
"confidential-port": 0
}
应用修改
1.修改之前创建的子模块keycloak-adapter-servlet,在resources下的keycloak目录中创建keycloak-confidential.json,内容如下:
{
"realm": "SpringBoot",
"auth-server-url": "http://localhost:8180/auth/",
"ssl-required": "external",
"resource": "adapter-servlet-credentials-1",
"credentials": {
"secret": "0e053b89-d87f-460a-92ec-adcd11ce6034"
},
"confidential-port": 0
}
2.修改FilterConfig类
将配置文件名称修改为keycloak-confidential.json,如下
测试
重启应用后,在浏览器中输入访问地址:http://localhost:8081/protected/resource,结果浏览器重定向到了Keycloak的登录页面,并提示用户登录
完整的地址如下:
http://localhost:8180/auth/realms/SpringBoot/protocol/openid-connect/auth?
response_type=code&client_id=adapter-servlet-credentials-1&
redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fprotected%2Fresource
&state=ade02c3f-4323-4888-b0cc-c5ad6dfd8a1f&login=true&scope=openid
其中,response_type值为code表示先获取code再用code换取Token的授权码流程,redirect_uri就是我们刚才访问的受保护资源。填写之前创建的用户名/密码为zhangsan/123456后,点击登陆,就能正常访问受保护资源了
示例代码地址
至此,就完成了使用Servlet Filter Adapter实现Token校验及授权码流程认证,代码地址如下:https://github.com/ywu2014/keycloak-demo/tree/master/keycloak-adapter-servlet
猜你喜欢
- 2024-09-08 粘土风格comfyui一键工作流,粘土一切你想粘的!
- 2024-09-08 企业级路由器 EdgeRouter 6P 开箱评测
- 2024-09-08 比好更好的电视盒子:泰捷W40PRO体验
- 2024-09-08 首发锐龙9 8945HS!ROG幻14 Air评测:性能最强的14寸轻薄本
- 2024-09-08 Surface Pro 4/Laptop推送Win10最新固件
- 2024-09-08 如何远程重置S7-1200/1500CPU(s7-1200远程io)
- 2024-09-08 全系列西门子PLC通过巨控GRM530模块远程上下载调试PLC梯形图
- 2024-09-08 Science上网的dns修正(电脑启动蓝屏0x0000006b怎么解决)
- 2024-09-08 如何远程调试西门子1200PLC(西门子远程调试模块)
- 2024-09-08 如何实现国外PLC西门子S7-1200远程下载监控维护方案
你 发表评论:
欢迎- 05-09Spring Boot3 RESTful 接口参数校验,这篇吃透就够了!
- 05-09《Spring6》第02节:基于XML方式搭建Spring6框架开发环境
- 05-09MapStruct架构设计(mapstruct @mapping)
- 05-09分布式微服务架构组件(分布式微服务架构设计)
- 05-09Java Swing组件下的JButton实例(java swing 组件)
- 05-09java基础都在这了,小主们拿去吧(java基础是指什么)
- 05-09AOP的实现落地(拦截过滤),一切都要从Servlet说起
- 05-09【Spring Boot】WebSocket 的 6 种集成方式
- 最近发表
-
- Spring Boot3 RESTful 接口参数校验,这篇吃透就够了!
- 《Spring6》第02节:基于XML方式搭建Spring6框架开发环境
- MapStruct架构设计(mapstruct @mapping)
- 分布式微服务架构组件(分布式微服务架构设计)
- Java Swing组件下的JButton实例(java swing 组件)
- java基础都在这了,小主们拿去吧(java基础是指什么)
- AOP的实现落地(拦截过滤),一切都要从Servlet说起
- 【Spring Boot】WebSocket 的 6 种集成方式
- Java 中五种最常见加密算法:原理、应用与代码实现
- 用注解进行参数校验,spring validation介绍、使用、实现原理分析
- 标签列表
-
- spire.doc (59)
- system.data.oracleclient (61)
- 按键小精灵源码提取 (66)
- pyqt5designer教程 (65)
- 联想刷bios工具 (66)
- c#源码 (64)
- graphics.h头文件 (62)
- mysqldump下载 (66)
- sqljdbc4.jar下载 (56)
- libmp3lame (60)
- maven3.3.9 (63)
- 二调符号库 (57)
- 苹果ios字体下载 (56)
- git.exe下载 (68)
- diskgenius_winpe (72)
- pythoncrc16 (57)
- solidworks宏文件下载 (59)
- qt帮助文档中文版 (73)
- satacontroller (66)
- hgcad (64)
- bootimg.exe (69)
- android-gif-drawable (62)
- axure9元件库免费下载 (57)
- libmysqlclient.so.18 (58)
- springbootdemo (64)
本文暂时没有评论,来添加一个吧(●'◡'●)