Keycloak与React集成应用(上篇):用户登录

  • A+
所属分类:前端开发

Keycloak是一个开源的身份和访问管理系统,它可以轻松与任何web应用集成,从而为web应用提供访问控制管理功能。

具体的Keycloak介绍请参见官方网站

本文的目的不是介绍keycloak的原理,而是介绍如何将keycloak与基于React的应用进行集成。

本文将实现一个具体的React应用,然后与keycloak集成,最终实现访问该React应用时的用户登录与验证功能。

Keycloak安装与配置

Keycloak以独立的服务的方式运行,它通过独立的服务向单个或多个应用提供集中式的服务。因此我们首先需要安装部署Keycloak服务。

Keycloak安装

首先在官方网站的下载页面下载Keycloak的软件包。

Keycloak与React集成应用(上篇):用户登录

下载后解压到某目录,然后打开cmd进入bin目录。

Keycloak支持集群模式和单机模式,我们以单机模式运行Keycloak,运行如下命令:

如果你看到类似如下的输出,就说明Keycloak成功安装并启动起来了:

接下来,我们在浏览器中输入url:http://localhost:8080,打开Keycloak管理界面。

首次打开界面时,需要创建一个管理账户。

创建好账户后,点击“Administration Console”:

Keycloak与React集成应用(上篇):用户登录

输入用户名密码,点击登录:

Keycloak与React集成应用(上篇):用户登录

登入后,进入Keycloak管理控制台首页:

Keycloak与React集成应用(上篇):用户登录

Keycloak配置

接下来介绍如何在Keycloak管理控制台中进行配置。

首次进入控制台,Keycloak默认有一个名为master的realm。我们需要创建我们自己的realm。例如我们这里创建一个名为“demo”的realm。

接下来创建用户,我们可以创建一个或多个用户,注意创建的用户只能登录用户所在的realm。这里我们创建一个用户“demo”。

创建realm和用户后,我们需要为我们的react应用创建一个client,这里命名为“keycloak-react-example”。创建client后,还需要设置几个必须的参数,参考下图:

Keycloak与React集成应用(上篇):用户登录

注意,对于web前端应用,Access Type必须是“public”。

Web Origins虽然不是必须的,但是一般都需要设置,以避免因跨域而无法访问的问题。

开发React应用

接下来,我们开发一个简单的React应用。

应用效果

首先来看看我们的应用的最终效果吧!

Keycloak与React集成应用(上篇):用户登录

  • 每当访问应用时,总是会被导向到用户登录界面,要求输入用户名及密码登录应用。
  • 登录应用后,会自动重定向到product页面。
  • 点击Product或Admin菜单,可以进入product或admin页面。
  • 在product或admin任何页面,点击Logout按钮,就可以退出登录,会被自动重定向到用户登录页面。
  • 输入用户名密码再次登录,会默认进入刚才退出时访问的页面。
功能页面开发

首先,我们开发功能页面,也就是product和admin页面。我们暂时不集成Keycloak,待功能页面开发好后,再集成keycloak。

要开发React应用,首选使用create-react-app脚手架。首先安装create-react-app(前提是你已经安装了npm):

接下来,使用create-react-app脚手架创建我们的应用项目结构:

运行命令后可以帮我们创建一个应用骨架,包括必须的一些目录结构及文件。

我们最终实现的代码结构如下所示:

Keycloak与React集成应用(上篇):用户登录

我们需要首先在根目录下的package.json中添加依赖:

创建的项目结构中主要包括public和src两个目录,主要的代码都在src目录下。

public下的index.html是应用的入口html文件。

src/components下包括product和admin的功能页面。src/images下存放应用使用的图片。src/routes下包含了定义应用导航的代码文件。

src/index.js是应用的入口js文件,我们首先在里面实现通过React在DOM中渲染我们的应用:

index.js中使用render方法渲染Page.js中定义的Page组件,Page.js代码如下:

我们在Page.js中定义了两个路由,第一个  表示当我们访问应用根“/”时,自动重定向到product页面。

第二个 表示会以App.js里定义的App组件渲染任何URL以“/app”开头的页面。

App.js代码如下:

App组件实现了我们应用的主页面结构,上面是一个Header,下面是应用的主体内容。

Header中部显示应用logo,左侧显示导航菜单,右侧显示当前登录用户,以及Logout按钮,这样用户就可以方便的从系统退出登录。

注意:我们现在还没有最终实现获取用户的getLoginUser()方法,只是简单的返回一个字符串,这样可以保证应用可以正常的运行并显示。

类似地,登出系统的onLogout()方法也只是一个空方法,我们目前让它不做任何事情,这样可以保证应用可以正常运行。

我们稍后在集成Keycloak时会实现这两个方法。

左侧的导航菜单定义了两个不同的Link,当我们点击某个菜单时,将导航到相应的页面。

页面下方的主体内容部分将显示当前选中菜单对应的页面内容,但是我们只有一行简单的代码  。让我们看看src/routes/index.js的代码内容:

可以看到,我们在这里对导航菜单的路由进行了定义。两个Link分别对应不同的组件,组件的内容将在主体部分显示。

下面是ProductIndex和AdminIndex组件的代码:

这里我们只是为了演示不同菜单对应不同页面,而页面中并没有什么实际的内容。

最后,应用用到的图片我们放在src/images下。各个页面用到的CSS代码放在src/App.css中。

现在我们的应用已经实现了,我们可以运行它来先看看效果:

启动后,会默认打开浏览器并访问:http://localhost:3000。不出意外的话,浏览器会马上重定向到http://localhost:3000/#/app/product/index,且可以正常看到我们的应用页面如下:

Keycloak与React集成应用(上篇):用户登录

集成Keycloak

我们的应用功能页面已经实现,接下来我们集成Keycloak实现用户登录登出功能。

引入keycloak-js

首先我们需要在package.json中引入keycloak的依赖:

运行如下命令安装keycloak依赖包:

导入keycloak配置

接下来,我们需要回到Keycloak的Administration Console下载keycloak配置文件。

登录Administration Console(注意:这里要使用第一次创建的管理帐号),点击左侧菜单中的Clients,选择我们创建的client:keycloak-react-example,点击“Installation”选项卡,在“Format Option”下拉选项中选择“Keycloak OIDC JSON”,点击出现的“Download”按钮,下载keycloak.json文件,内容如下:

最后,把下载的keycloak.json拷贝到应用的public目录下。

实现keycloak初始化

接下来,我们在src下创建keycloak.js文件,在其中实现keycloak的初始化等相关代码:

我们首先定义了一个KeycloakClient类来包装keycloak相关的一些对象和方法。

类构造器函数中初始化两个属性:

  •  表示keycloak是否已初始化。
  •  对象是使用Keycloak库提供的类创建的对象,我们需要传递前面下载的keycloak配置文件作为其构造函数的参数。  对象中包含了很多属性和方法,具体内容可以查阅Keycloak官方文档。我们暂时只会用到其中的  方法。

接着我们定义了  方法,传入了一个callback函数作为参数。方法中调用了前面创建的keycloak对象的init方法进行初始化,因为我们传入了  参数,keycloak将检查是否已登录,如果没有,keycloak会自动重定向到登录页面,等待用户登录。当用户输入正确的用户名及密码登录成功后,就会触发  里的回调函数。我们在success回调函数里设置initialized属性,并执行callback函数。

修改src/index.js

现在,我们需要修改src/index.js,修改后src/index.js如下:

我们首先引入keycloak.js,然后调用初始化函数,并在callback函数里调用  ,将初始化后的keycloak对象作为参数传递给render的组件:Page。这样可以保证只有在keycloak初始化成功后才渲染应用组件。

可以看到我们将keycloak对象作为props传给了Page组件:  。

我们需要这么做,因为我们希望把这个keycloak对象通过props传递给App子组件,然后从中取出当前的登录用户名进行显示,以及调用keycloak对象的logout方法实现退出登录。

修改Page组件

现在,我们只是把keycloak作为Page的props传递给了Page组件,但App组件还无法获取它。

接下来,我们将通过改造Page组件,实现将keycloak从Page组件传递给App子组件。

改造后的src/Page.js代码如下:

可以看到我们注释掉了  ,使用一行新的代码替换了它:

我们使用了自定义的PropsRoute组件,它扩展了Route。它可以把所有props传递给component指定的组件。

修改App组件

现在我们可以在App组件中获取Page的props了,而我们在index.js里把keycloak对象传递给了Page组件,因此我们可以在App组件获取keycloak对象了。

最后,我们可以改造src/App.js,实现之前的两个方法:getLoginUser()和onLogout()。

改造后的代码如下:

可以看到,我们从props对象中获取了keycloak对象,并从keycloak对象中获取了登录用户名  。在onLogout()方法中,我们使用了keycloak的自带logout方法  。

测试应用

现在,我们可以再次启动应用:

如果一切顺利的话,你将看到与我们前面所展示的应用效果完全一样的效果。

本文完整代码请参考这里

weinxin
关注微信
如有疑问,欢迎扫一扫左侧二维码添加微信好友进行咨询,我会第一时间回复您!
yglong

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: