转载

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

前面的文章讲过Spring Boot应用集成Keycloak实现统一身份验证、权限控制的方法,其中权限控制的部分直接使用Role进行判断,这种方式对于简单的系统来说也够用。但是对于复杂的需要集成细粒度权限控制的系统,显然只是单纯的依靠Role直接控制的方式是不合适的,并且应用本身与Role直接耦合的方式也很不灵活。本文讲述Spring Boot的Web应用如何集成Keycloak实现细粒度权限控制。

Keycloak核心权限概念综述

Keycloak支持细粒度权限控制策略,可以组合使用如下不同的访问控制机制:

  • Attribute-based access control (ABAC)
  • Role-based access control (RBAC)
  • User-based access control (UBAC)
  • Context-based access control (CBAC)
  • Rule-based access control
  • Time-based access control

Keycloak授权处理流程

如果要使用Keycloak的细粒度权限控制,主要有3个流程需要了解:

  • 资源管理(Resoucre Management)
  • 权限和策略管理(Permission and Policy Management)
  • 策略执行(Policy Enforcement)

资源管理

资源管理主要用来定义资源服务器的哪些对象需要被保护

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

其中资源服务、资源、范围(Scope)关系如下:

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

权限和策略管理(Permission and Policy Management)

策略是来定义满足哪些条件才可以访问资源,不过策略本身并不与资源关联。要想策略实际作用在相应的资源上,就需要配置权限,将要保护的资源及策略进行关联。

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

策略执行

策略执行需要在资源服务内集成一个 Policy Enforcement Point (PEP,资源执行点),以便与Keycloak服务进行通信获取相关的权限信息等,从而决定哪些资源可以被访问。

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

Keycloak细粒度权限控制后台配置

要想启用Keycloak的细粒度权限控制,需要先创建相应的客户端,并启用授权服务。然后根据上面的授权处理流程,进行资源管理、权限和策略管理的配置。本文模拟如下场景来进行配置,以便更好的理解配置内容。

场景如下:

  • 需要被保护的应用有 /admin/customer/view/customer/delete 三个主要资源
  • 拥有 ROLE_ADMIN 角色的用户可以访问所有资源
  • 拥有 ROLE_CUSTOMER 角色的用户仅可以访问 /customer/view ,其他资源不能访问

接下来便看下针对如上模拟的场景,在Keycloak后台具体要如何配置。

创建角色及用户

  1. 创建3个角色,其中 ROLE_USER 给所有用户都进行绑定

    Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
  2. 创建2个用户并绑定角色

    Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
    Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

创建客户端并启用授权服务

  1. 新建客户端

    Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
  2. 设置 confidential 访问类型,并启用授权

    Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

配置资源、策略及权限

在客户端的 Authorization Tab下,有很多子的选项卡,可以对资源、策略及权限进行配置。

Settings选项卡配置

Settings选项卡下的是关于授权的一些全局默认配置

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

这里说明下Settings下面的2个重要配置

  • Policy Enforcement Mode:指定授权服务器接受到请求时策略如何执行

    • Enforcing:当资源没有配置关联的策略时,请求默认被拒绝访问,这也是默认的选项
    • Permissive:当资源没有配置关联的策略时,请求允许访问
    • Disabled:禁用所有资源的所有访问策略
  • Decision Strategy:表示权限最终是如何计算的策略,以决定相应的资源是否能获得授权

    • Affirmative :至少一个权限计算做出正向决定
    • Unanimous:所有的权限计算都要做出正向决定

Resources选项卡配置

Resoucres选项卡主要是用来配置需要保护的资源。本示例中配置如下几个资源,注意下Scopes的设置

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

Authorization Scopes选项卡配置

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

Policies选项卡配置

Policies下主要配置哪些策略,配置的策略用来在权限设置中与资源进行关联,Keycloak本身支持很多策略,详细的策略说明可参考官方文档,本示例中使用最常使用的基于角色(Role Based)的策略

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

Permissions选项卡配置

Permission下就是用来配置资源、策略如何进行关联,并且在有多个策略关联时采用何种策略(Decision Strategy)最终决定资源是否能被授权,Decision Strategy的配置项与上文Settings下的意义相同,在此不再赘述

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

Spring Boot项目集成Keycloak代码配置示例

application.yml Keycloak配置

keycloak:
  realm: demo
  auth-server-url: http://127.0.0.1:8080/auth
  resource: spring-boot-authz-keycloak-web
  ssl-required: external
  credentials:
    secret: dede7fd6-2817-491c-b7e5-27f65bbb5fc7
  use-resource-role-mappings: false
  bearer-only: false
  autodetect-bearer-only: false
  security-constraints:
    - authRoles:
        - ROLE_USER
      securityCollections:
        - name: all
          patterns:
            - /*
  policy-enforcer-config:
    on-deny-redirect-to: /accessDenied
复制代码

配置文件说明可参考之前的文章,这里主要说下,有 policy-enforcer-config 配置项,表明当前应用启用细粒度权限控制, on-deny-redirect-to 表示当访问被拒绝时跳转的地址

Controller示例代码

@RequestMapping(value = "/customer/view", method = {RequestMethod.GET})
public String customerView(Model model, HttpServletRequest request) {
    KeycloakSecurityContext keycloak = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
    model.addAttribute("authz", keycloak.getAuthorizationContext());
    return "customer/view";
}

@RequestMapping(value = "/customer/delete", method = {RequestMethod.GET, RequestMethod.POST})
public String customerDelete(Model model, HttpServletRequest request) {
    KeycloakSecurityContext keycloak = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
    model.addAttribute("authz", keycloak.getAuthorizationContext());
    return "customer/delete";
}

@RequestMapping(value = "/admin", method = {RequestMethod.GET, RequestMethod.POST})
public String admin(Model model, HttpServletRequest request) {
    KeycloakSecurityContext keycloak = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
    model.addAttribute("authz", keycloak.getAuthorizationContext());
    return "admin/view";
}

@RequestMapping(value = "/admin/delete", method = {RequestMethod.GET, RequestMethod.POST})
public String adminDelete(Model model, HttpServletRequest request) {
    KeycloakSecurityContext keycloak = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
    model.addAttribute("authz", keycloak.getAuthorizationContext());
    return "admin/delete";
}

@RequestMapping(value = "/accessDenied", method = {RequestMethod.GET, RequestMethod.POST})
public String accessDenied() {
    return "access_denied";
}
复制代码

示例Controller主要是将Keycloak的授权上下文传给model,并指定相应的视图渲染

customer/view.ftl页面示例代码

<h1>Customer View</h1>
<div>
    <#if authz.hasScopePermission("delete")>
        <a href="/customer/delete">delete</a>
    </#if>
</div>
复制代码

页面使用freemarker,都比较简单,当然也可以使用其他视图引擎,此处仅贴出这一个页面的示例代码,只有拥有 delete Scope的权限才能够看到delete链接

项目效果演示

customer用户访问效果

访问/customer/view页面,看不到delete链接

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

访问/custome/delete、/admin页面,直接跳转/accessDenied页面

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

admin用户访问效果

admin用户访问/customer/view页面,可以看到delete链接

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

admin用户点击delete链接或者直接访问/customer/delete,都可以正常显示页面

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制

admin用户可以正常访问/admin相关页面

Spring Boot Web应用集成Keycloak进阶之细粒度权限控制
原文  https://juejin.im/post/5ef764fd6fb9a07e8223eae6
正文到此结束
Loading...