请教下 Spring Cloud GateWay 网关的鉴权和数据权限, 怎么把 token 转换成用户信息 进入其他服务?

2020-03-11 15:27:19 +08:00
 wuzhizuiguo

例如简单判断有没有权限调用某个接口,我在 gateway 里的 filter 判断一下这个 token 存不存在 redis 中(token -> 用户信息).

假设现在有个接口是 api.test.com/user/mail/list/ 接口, 需要传入 userId, 获取到这个用户的邮件列表, 怎么让 gateway 转发请求到 user-service 时, 将请求 header 里的 token 转化为 userId,

userController 里的方法可能是这样的 List<mail> mailList(Long userId);</mail>

除了网关外其他服务 RPC 调用该接口, 也可以只传入 userId 参数 这样的请问该怎么实现?

如果是以前的方法,我可能会把这个方法改为 List<mail> mailList(Long usrId,HttpServletRequest request);</mail>

然后取出 request 中的 token,去 redis 中验证一下, 然后去取出 userId, 但是这样 其他 b.c.d..服务要是 fegin RPC 调用 这个方法时, 就也需要传入 HttpServletRequest/或者 token.

请教下大佬,Spring Cloud GateWay 网关的鉴权和数据权限该怎么做?

7621 次点击
所在节点    Java
24 条回复
gaius
2020-03-11 15:40:47 +08:00
网关调鉴权服务完事把用户信息和权限列表写到 header
359889741
2020-03-11 15:41:23 +08:00
filter 里面读出 userId 来,再往业务服务传递不就行了
wuzhizuiguo
2020-03-11 15:45:51 +08:00
@gaius 谢谢. 这样在 user-service 里, 对应的方法怎么获取 header 里的写入的信息, 感觉需要在接收的 controller 方法里,添加上 HttpServletRequest 参数, 这样的话 admin 等其他服务也 rpc 调用这个接口 会不会有影响.
wuzhizuiguo
2020-03-11 15:49:48 +08:00
@359889741 谢谢, 这样感觉可行, 是收经过网关 需要鉴权的的都要 把 token 里的 userId 取出来了. 是指修改请求的参数, 把 userId 放入到 post 的请求 body 里 或者 get 的 param 中吗
hantsy
2020-03-11 16:15:49 +08:00
也就是说其它里面的 Service 不做安全验证,这样跟裸奔有什么差别。
hantsy
2020-03-11 16:17:58 +08:00
既然用到 Redis,直接上 Spring Session ( Redis )就好了,Session 里面想丢什么就什么了,一个用户对象也可以。
hantsy
2020-03-11 16:19:31 +08:00
用 Spring Session+Spring Security 控制安全就可以了,https://github.com/hantsy/spring-microservice-sample
wuzhizuiguo
2020-03-11 16:19:34 +08:00
@hantsy 这个我看网上是这样的, 其他的 service 不对外开放(放到内网 或者防火墙关了访问端口), 即经过网关校验后 各个服务之间是可以信任的.
hantsy
2020-03-11 16:26:01 +08:00
不知道这种思维方式哪里来的。。。
你网关是会对外吧,如果别人能够进入你网关呢?不一样可以再进入里面的服务。
wuzhizuiguo
2020-03-11 16:42:37 +08:00
@hantsy 是的.. 网关是对外的,如果网关通过了, 那按照我这种,确实是可以按照它的接口权限 访问对应的接口 /服务. 有博客也提到了 spring security . 谢谢, 我也去了解学习下
yang957862615
2020-03-11 17:09:45 +08:00
实现 GlobalFilter 接口之后使用 ServerWebExchange.getRequest().mutate().header(String headerName, String... headerValues)这个方法就行
wuzhizuiguo
2020-03-11 17:11:52 +08:00
@yang957862615 谢谢. 那再下个服务里怎么获取到这个 header 里的值呢? 感觉方法里还是需要添加 HttpServletRequest 参数...
yang957862615
2020-03-11 17:15:45 +08:00
@wuzhizuiguo springboot 可以在类里面注入 HttpServletRequest 实例就可以不用在方法上加这个参数
humpy
2020-03-11 17:19:59 +08:00
用拿 header 的注解就行了

@RequestHeader("X-USER-ID") String userId
caotian
2020-03-11 17:21:06 +08:00
如果 JWT 可以满足要求, 不需要用 redis 来存 token, gateway 可以只验证 jwt 是否有效, 然后取出 jwt 里的 userId, 转发请求的时候, 再把 userId 放到 header 里
wuzhizuiguo
2020-03-11 17:25:39 +08:00
wuzhizuiguo
2020-03-11 17:25:54 +08:00
@humpy 还可以这样.. 第一次看到 谢谢.
wuzhizuiguo
2020-03-11 17:27:03 +08:00
@caotian 谢谢. 是的, jwt token 也可以.
rykinia
2020-03-12 09:22:29 +08:00
@hantsy gateway 设置规则,让对外的接口为 /api/**。比如实际的接口是 /user,那么外网调用的 URI 则应该是 /api/user,然后 gateway 转发,这样外网应该没法直接通过 /user 访问吧
wuzhizuiguo
2020-03-12 10:44:05 +08:00
@humpy @RequestHeader("X-USER-ID") String userId 这个单纯请求是可以的. 但是其他服务 rpc 调用这个接口怎么办?
@PostMapping(value = "/list")
public Result list(@RequestHeader(value = "X-USER-ID", required = false) Long userId);
RPC 方法:
@PostMapping(value = "/user/mail/list")
public Result mailList(@RequestParam("userId") Long userId);

rcp 调用方法里里面的 userId,没有成功传入到 user-service,因为没有 header

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/651876

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX