zoukankan      html  css  js  c++  java
  • Spring Cloud微服务安全实战_6-4_权限控制改造

    上一篇说了认证,通过令牌可以知道当前用户是谁,并把令牌信息从网关到微服务,以及微服务与微服务之间传递用户上下文的信息,这一篇来聊一下授权。

    一、最简单的情况ACL权限控制

    用户有哪些权限直接在scope里写着,只要在程序里判断一下要访问某个方法,是否有访问权限就可以了这种适用于权限简单的场景。

    使用 @PreAuthorize("") 注解标记在Controller方法,可以控制,哪些请求有权限访问该服务。注意要想是该注解生效需要在启动类上加上注解: @EnableGlobalMethodSecurity(prePostEnabled = true)  使其生效。

    value值有两种表达式:

      1,@PreAuthorize("#oauth2.hasScope('fly')")  表示,scope包含“fly”的令牌,才可以访问该服务。这个针对客户端应用的,不能具体到某一个人。

      2,@PreAuthorize("hasRole('ROLE_USER')")  具体到每一个人,这个人包含哪些角色,就能访问,这个角色在认证服务器的 UserDetailsService  类的 loadUserByUsername 方法里获取。

    实验@PreAuthorize("#oauth2.hasScope('fly')")   :

      用orderService 客户端通过网关 ,获取token

      

       

       这个token的scope只包含 read,write ,但是创建订单服务需要token的scope包含fly才能访问,用这个token通过网关访问创建订单服务:

      

     将创建订单服务的权限控制表达式换成   @PreAuthorize("#oauth2.hasScope('write')")  就可以正常访问。

    实验@PreAuthorize("#hasRole('ROLE_USER')")   :

     通过网关获取令牌 

      

       创建订单服务,有ROLE_USER角色,才能访问

      

       认证服务器的UserDetailsService ,写死的权限,只有ROLE_ADMIN

      

      通过网关拿token 创建订单

         

       权限控制注解换为  @PreAuthorize("hasRole('ROLE_ADMIN')") ,则可正常调用创建订单服务。

    使用@PreAuthorize 注解处理简单角色很方便,但是没办法处理复杂的场景。如果权限总是变化的,这个就不适合了,因为权限控制是硬编码在Controller了,每次修改权限信息,还得重启服务。

    二、在网关上做复杂的权限控制

    假设已经有了一个权限系统,怎么跟网关接起来?

    1,在 GatewaySecurityConfig 配置类上,需要做如下的修改 

          a)  指定权限访问规则

      在 GatewaySecurityConfig.configure(HttpSecurity http) 方法里,配置 http.access("#permissionService.hasPermission(request,authorization)")  ,指定权限访问规则,permissionService需要自己实现,返回布尔值,true-能访问;false-无权限,传进去2个参数,参数1-当前请求 ,参数2-当前用户。

     b) 新建 PermissionService 接口以及实现类 ,实现自己的权限控制逻辑。

     c) 新建表达式处理 GatewayWebSecurityExpressionHandler

      只指定这个权限访问规则http.access("#permissionService.hasPermission(request,authorization)")是没用的,因为Spring不认识,所以还得新建一个类:GatewayWebSecurityExpressionHandler (表达式处理器),用来往权限表达式处理器里设置变量,变量名就是 permissionService,变量值是
      自定义的权限处理类
    PermissionService
     d)指定表达式处理器
     
        GatewaySecurityConfig.configure(ResourceServerSecurityConfigurer resources)里 指定 resources.expressionHandler(gatewayWebSecurityExpressionHandler)表达式处理器
    
    
    
     
    
    

     

     

     通过网关申请令牌,通过网关访问创建订单服务,有一半的可能性访问失败,一半可能性成功。

     到目前为止的项目框架结构是这样的:

     应该是有一个权限服务的,权限服务也是一个微服务,认证服务+权限服务=安全中心。

     目前的权限都在网关控制的,这样可能存在越权:

      比如你有权限访问订单服务,没权限访问库存服务,但是订单服务又调用了库存服务,这样就越权了。

    怎么解决这个越权呢:

      a)  可以在每个微服务上,都调用redis检查权限,做法和上边演示的在网关上的做法是一样的,但是不建议这么做,所有微服务都依赖redis是大量的耦合。

      b)  95%的细粒度的权限都在网关上做,微服务之期间互相调用的权限,只做一个粗粒度的黑白名单的控制,比如你一个结算服务,有一个白名单,只允许订单服务来调用,其他人调不了。(后面介绍sentinel怎么方便的进行黑白名单的控制)。微服务之间的调用不用像网关那么做细粒度的控制,(这个服务你能不能调,那个服务你能不能调),但是要有一个黑白名单的控制就可以了,控制住那些微服务之间能调用就可以了。

    代码 :https://github.com/lhy1234/springcloud-security/tree/chapt-6-3-permission 如果帮到了你给个小星星吧

  • 相关阅读:
    递归函数底层原理浅析
    lambda expression & mutable
    命令mv
    printf的参数
    程序结构之静态本地变量
    汇编.align指令
    程序结构之全局变量
    命令touch
    更改gcc默认版本,实现gcc版本升降级
    命令chmod
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/12496957.html
Copyright © 2011-2022 走看看