把在微服务里面写的安全的相关逻辑挪到网关里面来。这样把安全逻辑和业务逻辑解耦开。那么这些问题就都解决了。
先来看下之前的安全的代码,首先在之类做了认证,认证服务器去认证,拿这个token去换用户信息。
认证完成后,又在这里做了个简单的授权,盘点当前的用户是不是有读权限和 写权限。
在这里还根据resourceId有一个简单的权限控制,就是我的令牌只能访问哪些resourceServer
之前基本上做的就是认证和授权,在网关上,所有的请求都要走网关转到这个微服务上。所以在网关上不光要做认证和授权,之前说的认证机制都要加到网关上,包括限流。
网关上写代码-认证
建一个新的filter包
写一个filter
要继承ZuulFilter
@Component声明称一个Spring的组件
任何一个继承了ZuulFilter的过滤器都会有四个方法需要覆盖。
写一段逻辑判断过滤器是不是要起作用,这里我们返回true。就是永远起作用。
run里面是我们真正要写的业务逻辑
FilterType过滤器的类型,zuul提供了四种过滤器的类型,这里可以写四个字符串。
从这四个里面挑一个来返回。根据你的实际情况。route是用来控制路由的,一般我们不会自己去写这个东西,因为zuul替我们做了这个事了。一般我们写前三个,pre就是在业务逻辑之前会执行过滤器里面的逻辑,也就是run方法里面的逻辑
post是在业务逻辑执行之后,执行run里面的逻辑
error是说在业务逻辑抛出异常之后,我们去会执行run里面的业务逻辑。
大部分情况下我们都是写pre。我们现在做安全用到的都是pre
filterOrder控制过滤器的执行顺序。我们之前也讲了 我们几种安全机制认证、审批、授权 限流是有顺序的,就是通过这个字段来控制。这里我们写一个1
开始写认证的逻辑
run方法里面是真正的逻辑。这里加上@Slf4j
在我们的订单服务里面的认证逻辑,他是直接发http请求到认证的服务器上。然后获取token它的信息。
同样的我们在filter里面也要做这个事
requestContext是用来获取请求和响应的。帮我们拿请求响应对象。
request就是拿到了当前的请求。
如果是发往认证服务器的 ,就直接返回了。因为这是去要做验证的。return null 就是走下一个filter了。
不是token请求的 ,就获取到请求头,Authorization。如果请求头是空 就返回null。在认证这个环节,不管是成功还是失败都要往下走。在这里不会拦截请求,不让往下走的。不管认证信息有没有,也不管认证信息对不对 ,都要往下走。
忽略大小写来判断 请求头是不是以bearer+空格 开头
tokenInfo
tokenInfo实际上就是调用check_token的返回
我们把他封装到tokenInfo这样的类里面
active:标明令牌是不是可用的
client_id:这个令牌是发给哪个客户端应用的
scope是一个数组
user_name:这个令牌是发给哪个用户的
aud:就是之前说的resourceId,就是这个令牌可以访问哪些资源服务器的id的数组。
exp:令牌的过期时间
authorities:用户对应的所有的权限
在认证服务器上发令牌的时候给所有的用户都设置了一个权限叫做ROLE_ADMIN
那么最终我们拿到令牌信息的时候,就是这个authorities
现在声明了一个叫做TokenInfo的对象,来封装check_token的响应
下面来创建getTokenInfo这个方法
首先是substring截取bearer后面的token
发送请求,在请求头上要带clientId、clientSecret,那么我要写一个HttpHeaders来带这些信息
因为我这个check_token的服务并不是一个rest服务,他不是发json请求的。所以我要告诉它 我发的是一个表单。
这个信息实际上在我的认证服务器上 没有注册。
我们之前只注册了 orderApp和orderService
现在把gateway也注册上。直接照抄上面一行就可以。这样我们就多了一个gateway的应用。这个引用申请的令牌也是只能访问order-server
最后再带上令牌的信息。注意这里只能用MultiValueMap,不能用hashMap等,会报错 跑不通。
然后把所有的信息组装成一个HttpEntity,HttpEntity的泛型就是param的MultiValueMap
注意这个HttpEntity是Springframework下的
把param和header都放进去。
发送请求
在上面声明restTemplate
结束