Keycloak与React集成应用(下篇):基于角色的访问控制

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

在上一篇《Keycloak与React集成应用(上篇):用户登录》中,我们介绍了如何将keycloak集成到基于React的前端应用中,实现用户登录验证功能。本文将在上一篇实现的已有功能之上,继续实现用户访问控制的功能,演示如何使用keycloak轻松地对应用的访问进行控制。

基于角色的访问控制(Role Based Access Control)

Keycloak设计非常灵活,支持多种访问控制方式,其中最简单的方式是基于角色的访问控制。

本文将演示这种最简单的,基于角色的访问控制。

在上一篇已有的用户登录验证功能之上,我们进一步实现对登录用户的访问进行控制。例如某些用户只能访问应用的某些页面。

我们将基于用户所分配的角色来限制用户可以访问的内容。

例如对于本应用,我们最终实现的效果描述如下:

  • 用户“demo”只分配了访问product页面的角色(Product_Role),因此当使用“demo”用户登入应用后,菜单中只显示了“Product”菜单项,该用户只能访问product页面,如下图所示:

Keycloak与React集成应用(下篇):基于角色的访问控制

  • 如果“demo”用户试图手动在浏览器地址栏中输入访问admin页面的url,将看到如下图所示的“对不起,你没有权限访问该页面!”的提示页面:

Keycloak与React集成应用(下篇):基于角色的访问控制

  • 而当使用同时具有Product_Role和Admin_Role角色的“admin”用户登录应用后,将可以同时看到“Product”和“Admin”两个菜单项,并且两个页面都可以访问,如下图所示:

Keycloak与React集成应用(下篇):基于角色的访问控制

配置Keycloak

现在让我们来实现上述的访问控制功能吧。

首先,我们需要在keycloak中创建用户及角色,并为每个用户分配适当的角色。

在上一篇中我们已经创建了demo用户,现在我们再创建一个admin用户。

然后创建角色。在Keycloak的Administration Console中,选择“demo”realm,选择左侧菜单中的“Roles”,点击“Add Role”按钮,分别创建两个角色:Product_Role和Admin_Role,创建后如下图所示:

Keycloak与React集成应用(下篇):基于角色的访问控制

接着我们为创建的两个用户分配角色。

选择菜单中的“Users”,点击“View all users”,将显示所有用户。

选择某个用户,例如admin,然后选择“Role Mappings”选项卡,为用户分配角色。如下图所示,我们为admin用户同时分配了“Product_Role”和“Admin_Role”:

Keycloak与React集成应用(下篇):基于角色的访问控制

同样的步骤,我们为demo用户只分配“Product_Role”,为了演示使用demo用户访问admin页面时,显示权限不足的提示页面。

在React应用中实现访问控制

接下来,让我们编写代码,在React应用中实现前面所演示的访问控制效果。

创建访问控制配置文件

首先,我们在public下创建一个访问控制的配置文件access_config.json,内容如下:

配置文件表明,访问product页面必须要有Product_Role角色,访问admin页面必须要有Admin_Role角色。当然我们也可以配置访问某个页面需要具有多个角色。

加载配置文件,实现访问控制判断方法

我们再次回到上一篇创建的src/keycloak.js文件中,为KeycloakClient类实现两个新的方法:

  • 加载访问控制配置文件的方法:
  • 判断是否可以访问某页面的方法: 

首先,在KeycloakClient类中添加读取配置文件的方法:

注意:在方法中使用了同步Ajax请求下载配置文件。

我们需要在构造函数中调用上面的方法,使得在实例化KeycloakClient对象时加载配置文件:

接着,在KeycloakClient中添加判断是否可以访问某页面的方法:

该方法中,我们根据传入的访问路径,从加载的访问控制配置中查找访问该页面需要具有哪些角色,然后调用keycloak内置的  方法逐个判断该用户是否具有所要求的所有角色。一旦该用户没有某个要求的角色,就返回false,表示该用户没有访问该页面的权限。

最后src/keycloak.js文件的完整代码如下:

实现权限不足提示页面

实现访问控制的核心方法已经实现了,接下来让我们在应用中使用它实现页面的访问控制。

在这之前,由于我们需要在用户没有访问某页面的权限时,提示权限不足的页面。因此我们需要先实现一个显示权限不足的新页面。

在src/components下新建一个pages目录,在其中新建一个Denied.jsx文件,我们在其中实现一个Denied的React组件,用于显示权限不足的信息,代码如下:

修改路由,根据权限判断结果进行跳转

那么,当用户访问某页面时,如何实现根据判断结果实现不同的跳转呢?我们可以修改路由组件的行为来实现。

让我们再次回到src/routes/index.js文件中。在上一篇中,我们创建了一个扩展路由组件Route的PropsRoute组件,它实现了将keycloak对象通过props传递到Route的目标组件中(即,component属性指定的组件)。

我们可以在该扩展组件的基础之上进一步扩展,加入判断访问权限的逻辑。

为了更好的说明组件的含义,我们更改了扩展组件的名字为  ,代码如下:

可以看到,我们调用了前面实现的  方法对传入的path进行判断,如果有权限,返回一个渲染目标组件的Route,如果没有权限,则返回渲染Denied组件的Route。

然后,我们将路由组件的代码进行修改,使其使用新修改的PrivateRoute组件替代上一篇的PropsRoute组件。

修改后的src/routes/index.js完整代码如下:

根据权限判断结果显示不同菜单项

最后,我们在src/App.js中实现根据权限判断结果,显示不同的菜单项。最后达到只显示有权限访问的页面对应的菜单项。

类似上面的扩展路由组件,我们创建一个扩展Link的组件  组件。代码如下:

扩展组件中,同时使用了前面提供的  方法判断是否可以访问传入的path,如果可以访问,就返回Link组件。如果不可以访问,就返回空,从而不显示内容。

然后,我们把App组件中的Link组件替换为新建的  扩展组件。

最后src/App.js的完整代码如下:

测试效果

至此,keycloak的配置,以及React中的代码已经全部实现,我们再次启动应用来看看效果吧:

如果一切顺利,你应该可以看到与本文开始所演示的完全相同的效果。

小结

本文介绍了使用keycloak实现基于角色的访问控制功能,这是keycloak提供的最简单的访问控制的方式。

实际上,keycloak还提供了更细粒度的访问控制方式,如基于权限(permission)的访问控制,它结合了资源(resource),scope和policy,可以实现更细粒度的访问控制。这是Keycloak提供的授权服务(Authorization Service)的高级功能。我会在后续的文章中介绍此功能。

本文的完整代码请参考这里

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

发表评论

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