微服务安全中心的架构

文章目录

  • 创建微服务基础服务
    • 1. 创建订单,库存模块
    • 2. 创建认证服务器:
    • 3. 创建资源服务器:知道自己是资源服务器,知道自己叫啥,知道自己怎么验证令牌
    • 4. 持久化客户端配置,持久化
  • 基于Zuul网关开发
    • 实现基于网关的安全逻辑
      • 具体实现
      • 转发配置
      • 流量控制配置
      • ZuulFilter接口
    • 实现前端服务器完整实现微服务架构
  • JWT改造微服务框架
    • JWT认证改造
      • JWT改造认证服务器
      • JWT改造网关服务器(认证和授权)-springsecurity已经做好了
  • 熔断限流
    • 熔断器状态机
    • 热点限流规则
    • Sentinel之配置持久化

微服务最重要的是解耦,而不是代码重复
短时多次,记录重复

创建微服务基础服务

微服务安全中心的架构_第1张图片

1. 创建订单,库存模块

2. 创建认证服务器:

  1. 添加依赖:boot-starter-web,cloud-starter-aouth
  2. 继承AuthorizationConfigAdaptor创建认证服务器配置类
  3. 配置客户端详情
  4. 配置认证服务器访问点,传入认证管理器
  5. 继承WebSecurityConfigurerAdapter创建security默认配置类
  6. 配置认证管理器,注入UserDetailService,以及加密器等

根据scope控制各个资源服务器的读写权限。

3. 创建资源服务器:知道自己是资源服务器,知道自己叫啥,知道自己怎么验证令牌

  1. 继承ResourceServerConfigurerAdaptor创建资源服务器
  2. 配置自己的resourceId
  3. 继承WebSecurityConfigurerAdapter创建security默认配置类
  4. 注入AuthenticationManager,并传入RemoteTokenService,进行认证token
  5. 注入RemoteTokenService,并传入客户端id,客户端secret,验证token的重定向url,token转换器(将token转换为用户信息)
  6. 通过@AuthenticationPrincipal注解获取用户信息

4. 持久化客户端配置,持久化

  1. 认证服务器添加依赖boot-starter-jdbc,mysql-connector
  2. 注入数据源,tokenStore
  3. 配置客户端详情,传入数据源,自动寻找数据库的oauth_client_details的数据进行配置;传入tokenStore对象,自动寻找数据库的oauth_access_token的数据进行配置

基于Zuul网关开发

问题:

  1. 资源服务器的 安全逻辑和业务逻辑耦合,增加了变更成本 |—网关负责验证令牌,解耦
  2. 随着业务节点增加,认证服务器压力成倍增大 |—只需增加网关的规模
  3. 多个微服务同时暴露,增加了外部访问的复杂性 |—应用只知道网关
    微服务安全中心的架构_第2张图片

实现基于网关的安全逻辑

具体实现

  1. 添加依赖boot-starter-web,cloud-starter-netflix-zuul
  2. 配置路由转发:zuul.routes.token.url: localhost:8080 //以token开头的路由转发到8080
    zuul.routes.order.url: localhost:8081 //以order开头的路由转发到8081
  3. 继承ZuulFilter实现认证逻辑(验证令牌):通过Authorization获取token,通过restTemplate向认证服务器发送请求获取tokenInfo信息,将其存储到request域供其他位置获取。
  4. 继承ZuulFilter实现审计日志。
  5. 继承ZuulFilter实现授权逻辑,先从request域获取tokenInfo,如果认证失败响应401错误,如果认证成功但没有相应权限响应403错误。
  6. 引入cloud-zuul-ratelimit框架实现流量控制,自定义错误逻辑处理,自定义key生成逻辑(按key计量) 429太多请求

注意:
a)网关不适合细粒度限流,因为它不能对内部相互请求限流,它适合对硬件能力进行限流,
b)网关不适合业务层面限流,业务修改网关也跟着改

转发配置

server:
  port:9070
zuul:
  routes:
    token:
      url: http://localhost:9000
    order:
      url: http://localhost:9001
  sensitive-headers:   //配置不往后边发的请求头

流量控制配置

server:
  port:9070
zuul:
  ratelimit:
    enabled:true
    repository:JPA
    default-policy-list:
      --limit:2              //每秒2个请求
        quota:1              //所有请求消耗的时间
        regresh-interval:1   //每秒
        type:
          -url               //单独计数
          -httpmethod

ZuulFilter接口

shouldFilter()  //是否发生作用
run()  //过滤逻辑
filterType()  //pre,post,error,route    业务逻辑执行之前/之后/出现错误
filterOrder()  //过滤器执行顺序

TokenInfo={
boolean active;
String clientId;
String[] scope;
String userName;
String[] aud; //令牌能访问的资源服务器id
Date exp; //令牌的过期时间
String[] authorities; //令牌所属用户的权限
}

实现前端服务器完整实现微服务架构

微服务安全中心的架构_第3张图片
**注意
a)自己写的类优于框架写的同名类
b)admin模块发送请求以/api开头发送给网关,不以/api开头自己处理
c)refresh_token模式需要单独设置userdetailService获取用户信息,认真管理器支持前四种授权类型
**

账号密码模式:
3. 创建Admin项目代替Node.js作为前端服务器
4. 填写表单登陆后向Admin模块发送请求,Admin通过RestTemplate远程调用网关获取token,若获取token成功,则存入session然后返回登陆成功
5. 实现ZuulFilter从session拿出token加到请求头,实现请求时携带token的功能
6. 实现登出功能:从request获取session失效掉就可以了
问题:
7. 安全性:前端应用使用用户名密码向getway获取令牌,能接触到用户名密码
8. 耦合:前端应用每次都要处理登陆逻辑,如果登陆逻辑改变,则所有前端应用都要重新部署
解决:
浏览器直接访问认证服务器完成认证,使得前端应用不会接触到密码,也不用处理登陆逻辑
a) 授权码模式,使得用户名密码和客户端应用密码都不用存储到浏览器中,保证了数据安全。适合用在web应用
b) 账号密码模式,将用户名密码发到客户端应用,客户端应用向认证服务器认证。适合用来app中,完全相信app得数据安全
c) 简化模式(不用):浏览器向认证服务器认证,然后返回访问令牌
d)客户端模式:客户端直接向认证服务器进行认证,然后返回访问令牌
微服务安全中心的架构_第4张图片
发送令牌请求时,是通过网关访问的认证服务器
在这里插入图片描述
微服务安全中心的架构_第5张图片
授权码模式改造
9. 浏览器向认证服务器请求授权码,携带参数client_id,redirect_url,responce_type(授权模式),state(客户端当前状态)
10. admin应用创建回调控制器,携带授权码通过网关向认证服务器请求token,若获取成功则将token保存到session中并返回成功
11. 认证服务器向admin增加授权码模式,并将admin模块的跳转地址配置到oauth_client_details(防止被篡改)

问题:只要认证服务器的session有效,就认为用户已经登陆,所以在退出时,需要将认证服务器的session失效。
a) 客户端应用的session有效期,控制多长时间跳转一次认证服务器
b) 认证服务器的session有效期,控制多长时间需要用户输入一次用户名密码
c) token有效期,控制登陆一次能访问多长时间微服务

退出逻辑改造
12. 浏览器退出时,访问认证服务器的退出方法,并配置重定向地址为前端服务器的登录页(而不是认证服务器的默认登录页)
13. 认证服务器重写退出逻辑,携带重定向地址自动提交确认页,当退出成功后,重定向到相应地址

认证服务器集群改造
14. 使用spring session实现认证服务器集群共享session,通过数据库或redis进行共享session,可配置session超时时间
避免session有效,但是token过期了
15. 改造网关的认证逻辑,从request获取到token,若token过期了,则通过refresh_token更新token,最后将token添加到请求头中
16. 若刷新令牌错误,则抛出异常,前端拦截该异常然后进行登出
基于session的sso:
a) 安全,可控性高,跨域
b) 适用于百万用户一下和内部管理系统(适合中小型公司的内部管理系统)
c) 复杂度较高,性能低,占用服务器资源(用户上亿就不行)
基于浏览器中cookie实现sso
17. admin模块回调控制器,携带授权码通过网关向认证服务器请求token,若获取成功则将access_token和refresh_token保存到cookie中
18. 在网关创建cookie过滤器,从cookie中获取access_token,若已过期则通过reresh_token更新acess_token,然后将其加到请求头里
19. 在网关创建me过滤器,从request容器获取到当前登陆用户
20. 前端编写退出逻辑,将cookie失效
基于cookie的sso
相对不安全,可控性低
复杂度低,不占用服务器资源,性能高
适用于上千万,上亿的用户

JWT改造微服务框架

JWT认证改造

问题
a) 效率低:每次都要从认证服务器获取用户信息 ——无需重新通过token获取用户信息,token本身就自包含
b) 不安全:传递用户身份通过明文用户名访问 ——只需传递令牌就知道用户信息
c) 繁杂:每个服务都需要传递令牌
解决:使用JWT解决上诉三个问题

JWT改造认证服务器

  1. 认证服务器将jdbcTokenStore替换为JwtTokenStore(JwtAccessTokenConverter设置签名)
  2. 字符串的签名替换为https的证书,通过keyStoreKeyFactory(证书,整数密码)获得密钥对

微服务安全中心的架构_第6张图片
注意:
resourceId控制认证服务器可访问哪些资源服务器
使用@AuthenticationPrincipal从令牌获取登陆用户名称
springSecurity已经实现了上述认证和授权逻辑

JWT改造网关服务器(认证和授权)-springsecurity已经做好了

细粒度权限90%都是网关做的
微服务之间的权限通过白名单实现
微服务安全中心的架构_第7张图片

  1. 网关服务器添加cloud-starter-oauth依赖,配置获取token_key的地址,路由转发地址,以及客户端id和secret //启动时从认证服务器获取签名token_key
  2. 网关服务器配置放行/token**,前端服务器通过授权码向网关申请令牌
  3. 创建网关服务器启动类,添加@EnableZuulProxy启动网关服务
  4. 订单服务器添加cloud-starter-oauth依赖,通过@AuthenticationPrincipal从令牌获取登陆用户名称
  5. 订单服务器注入Oauth2RestTemplate,它可以自动将token添加到请求头向下传递 //解决了令牌如何传递
  6. 针对于权限访问列表,可以在业务方法上配置权限@PreAuthorize("#oauth2.hasScope(’'fly)"),然后通过@EnableGlobalMethodSecurity(prePostEnabled=true)启动这种方式。hasScope只能针对某客户端做权限控制,hasRole针对用户做权限控制
  7. 针对基于角色的访问控制,通过表达式配置权限服务access("#permissionService.hasPermission(request,authentication)"),然后自定义授权的相关逻辑
  8. 继承Oauth2WebSecurityExpressionHandler实现一个表达式处理器,并设置授权服务,然后将表达式处理器配置到网关配置类
  9. 继承Oauth2AccessDeniedHandler处理403异常并记录日志,然后配置到网关配置类
  10. 继承AuthenticationEntryPoint处理401异常并记录日志,然后配置到网关配置类
  11. 继承OncePerRequestFilter实现一个日志过滤器,将其配置到ExceptionTranslationFilter(处理401-403异常)之前
    微服务安全中心的架构_第8张图片
    自定义的组件:增加或者改变框架默认实现

熔断限流

在微服务环境下,服务之间是存在相互依赖的,当某服务A响应时间变慢,依赖该服务的服务B也会收到影响,当服务B线程达到机器限制时,依赖服务B的服务随之也会收到影响

熔断器状态机

默认熔断器处于关闭状态,当达到配置的失败指标时,熔断器会变成打开状态,限制请求到达后续服务;当达到熔断时间间隔时熔断器会变成半打开状态,这种状态自会放行一个请求,若这个服务正常执行则恢复为关闭状态,否则继续变为关闭状态
微服务安全中心的架构_第9张图片

  1. 在Sentinel dashboard配置熔断规则
  2. 在需要降级的资源上添加@SentinelResource(value=“createOrder”,blockHandler=“降级方法名”),然后自定义降级方法

热点限流规则

场景1:为热点商品配置热点限流规则,然后为系统预留QPS
对于同一个资源,根据不同的参数,设置不同的限流规则

  1. 在需要限流的资源上添加@SentinelResource注解
    微服务安全中心的架构_第10张图片
    微服务安全中心的架构_第11张图片

Sentinel之配置持久化

微服务安全中心的架构_第12张图片
微服务安全中心的架构_第13张图片

  1. 安装zk
  2. 从github下载sentinel项目
  3. 打开zk的依赖,指定使用zk保存规则数据
  4. 改造客户端添加sentinel-datasource-zookeeper依赖,然后配置zk地址,自定义zk配置类将具体规则注册到对应管理器

你可能感兴趣的:(微服务)