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 如果帮到了你给个小星星吧

猜你喜欢

转载自www.cnblogs.com/lihaoyang/p/12496957.html
今日推荐