一步步学习Keycloak(认证篇)

上一篇讲解了Keycloak的功能以及如何使用Docker安装Keycloak,以及创建Keycloak用户,组等功能,这一篇我将详细介绍如何在Nginx中集成Keycloak,并在Nginx中实现对Client的认证,也就是实现一个Keycloak的Nginx client adapter。

为什么要在Nginx中集成Keycloak

Nginx作为目前最为流行的开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。因此无论是Web网页或者微服务都可以通过Nginx对外发布并实现负载均衡,如果能在Nginx里完成用户认证和授权就会简化在各种语言平台上的工作。比如前端可能是javascript开发,可能用的框架也不尽相同,有的是Reactjs,有的是VueJS等。后端开发语言更多,包括Java,C#,NodeJS, Go等。每种语言还有不同的框架,比如Java下就有Spring MVC,Servlet,SpringBoot,Security with SpringBoot等。因此如果在各种框架下都分别集成Keycloak,有几个问题,第一,对于开发者来说,可能就需要了解在各种框架下的Keycloak client adapter,然后分别实现,对于开发者的要求比较高,因此开发难度比较大。第二,这种方式也对代码侵入,需要在代码中完成认证和授权,而且需要有配置文件,特别是微服务,每个微服务里都要有认证授权的代码和配置,如果发生改动,所有的微服务都需要做相应的变更,因此不便于代码的升级和维护。

如何实现

知道了Nginx中实现Keycloak client adapter的重要性,就开始着手实现此功能。因为Keycloak有很多已经实现的client adapter,所以首先想到的是是否能从Github上找到nginx的client adapter。所以在google里一番搜索和比较,有几个比较合适的方法,但最为合适的还是oidc-proxy,这个库实现了容器,而且把需要的配置参数都已环境变量的方式暴露出来,很方便部署和配置,感觉比较符合我的需求。下面我将使用此库来实现的是利用Keycloak的OpenID Connect对用户进行身份验证以及遇到的一些列坑记录下来。

Nginx client的OpenID架构图

此架构图有Nginx,Keycloak,后端微服务和前端应用几个主要组件。前端应用访问Nginx代理的资源或微服务,Nginx做为Keycloak client将请求Keycloak进行认证和授权,Keycloak adapter将是我们需要实现的模块,与Keycloak的交互在此模块中实现。Keycloak作为认证和授权服务器,需要管理用户,资源,权限等,应用程序也可以通过admin client来对Keycloak进行远程管理。

配置Keycloak

上一篇我介绍了一些基本的Keycloak安装和配置,包括使用Docker安装keycloak,配置realm和用户。我们仍然需要这些基本配置,此外我们需要创建一个新的client。使用admin和你的初始密码登陆到Keycloak,图例如下。

创建领域(Realm)

创建一个以nginx命名的realm,并且打开enable开关,其他参数保持默认设置即可。

创建用户

因为我们实现认证和授权功能,肯定离不开用户,我们创建一个新用户,取名为auser,并为其设置密码,如下图。

创建client

Client一般是一些应用和服务,这些应用和服务需要请求Keycloak去认证和授权,并提供单点登录解决方案。我现在需要实现的是将Nginx作为一个client,去请求Keycloak进行认证和授权,因此,创建一个以Nginx命名的client。打开Keycloak的clients发现里面有很多内置的clients,比如account,adminclient,realm-management等,这些clients都Keycloak里一些内置的功能,比如Keycloak的rest api,realm management等,访问这些内置的服务时同样需要通过Keycloak来进行授权才能访问。我们将实现如何使用openid协议进行认证和授权,因此client protocal选择openid-connector。

创建完client后,需要设置client的访问方式,access type可以选择public,confidential,bearer-only。选择confidential方式,需要用户名和密码的登陆方式。打开Authorization Enabled,然后保存。保存完后,会出现Credentials标签页,里面有secret,这个在进行认证时需要提供。如下图,

部署后端服务

这个是用来模拟后端的服务,网页或者其他资源等,比如项微服务,前端程序等,这些资源将通过Nginx反向代理访问,为了快速的Demo Keycloak的认证功能,我部署了一个非常简单nodejs的hello world程序。
代码如下(server.js):

var http = require('http')
var port = 4000
var server = http.createServer(function (request, response{
  response.writeHead(200, {'Content-Type''text/plain'})
  response.end('Hello World\n')
})
server.listen(port)
console.log('Server running at http://localhost:' + port)

Dockerfile如下:

FROM node:4.2
COPY . /src
RUN cd /src && npm install
EXPOSE 4000
CMD ["node""/src/server.js"]

然后运行docker build,build完docker image后,启动该容器

docker build -t hello-world .
docker run -d -p 4001:4000 hello-world

此容器运行后,可以访问http://{你机器ip地址}:4001来访问此服务,正常会显示hello world

Nginx里集成Keycloak

完成上面的所有配置后,就来到了最为核心的功能,如何在Nginx中集成Keycloak来完成对资源的认证和授权。我们使用的client protocol是open id,对于OpenID的认证方式,完成的流程如下。

我们将使用开源的oidc-proxy来实现在Nginx中集成Keycloak,关于oidc-proxy的使用详情,可以参考Github上的介绍,在使用这个库的过程中,会遇到很多的问题,因为它没有详细的文档,可以通过阅读源码来了解实现原理,最大的坑是这个库没有完成授权功能,只是做到了认证功能,下一篇文章我将介绍如何在这个库的基础上进一步开发授权功能。

安装oidc-proxy
sudo docker run -e OID_DISCOVERY=http://192.168.1.9:8080/auth/realms/nginx/.well-known/openid-configuration \
 -e OID_CLIENT_ID=nginx -e OID_CLIENT_SECRET=b24019ef-89fe-4c9c-86cb-63da5a8addf7 \
 -e OID_SESSION_NAME=bps  \
 -e OID_REDIRECT_PATH=/redirect_url \
 -e PROXY_HOST=192.168.1.9 \
 -e PROXY_PORT=4001 \
 -e PROXY_PROTOCOL=http \
 -p 80:80 \
 -v /usr/local/openresty/lualib/resty/openidc.lua:/usr/local/openresty/lualib/resty/openidc.lua \
 -v /usr/local/openresty/nginx/lua/auth.lua:/usr/local/openresty/nginx/lua/auth.lua \
 -v /usr/local/openresty/nginx/conf/:/usr/local/openresty/nginx/conf/ \ evry/oidc
-proxy

在运行这个容器中,几个重要的环境变量需要指定:

  • OID_DISCOVERY,这个参数比较重要,而且是最大的一个坑,因为文档中提到的是OID_DISCOVERY=https://my-auth-server/auth,而且其他的Keycloak client adapter,比如spingboot等也配置的是auth,但如果按照这个配置,会抛出找不到authorization_endpoint异常。可以试着去访问我提供的这个配置endpoint,它会返回一个json对象,里面有各种endpoint,其中authorization_endpoint就是其中的一个endpoint。这些endpoint在openidc.lua中大部分都会用到,因此必须配成这个网址,在大牛同事的帮助下才得以解决,非常感谢。

  • OID_CLIENT_ID:此环境变量就是在keycloak中指定的client name

  • OID_CLIENT_SECRET:此环境变量就是创建完client后,指定acess type为credentials并打开authorization enable后出现,会出现secret值

  • OID_SESSION_NAME:此环境变量是创建的session name

  • PROXY_HOST:此环境变量是你的服务或资源部署的机器名或IP

  • PROXY_PORT:此环境变量是服务的端口

映射了此容器的端口80,以及外挂了此项目的源码文件和配置文件,这么做的目的是为了下一章,如何在oidc-proxy上继续完成资源的授权做准备,把源代码外观出来,容易开发和调试。

测试

访问http://[你的ip地址],会出现keycloak的登陆页面,并且页面Title换成了我们配置的Nginx,使用之前你创建的用户auser登陆,登陆完成后,会出现hello world,说明已经完成了使用Keycloak对Nginx发过来的请求进行用户认证功能。

下一篇,我将详细介绍Keycloak的授权机制,以及如何在Nginx中实现通过Keycloak来完成对服务的授权,将会在oidc-proxy现有功能的基础上开发授权功能,欢迎关注。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341