V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MeloForsaken
V2EX  ›  程序员

网关转发到鉴权,鉴权再转到业务怎么写?

  •  
  •   MeloForsaken · 2021-11-24 16:21:11 +08:00 · 4660 次点击
    这是一个创建于 1090 天前的主题,其中的信息可能已经有所发展或是发生改变。
    1. 如何把到网关的请求都转发到鉴权服务上?这个 route 得怎么写?
    2. 转发到鉴权服务上的请求,鉴权后如何再转发到业务上?是重定向到业务服务上?怎么知道端口和 IP ?还是再转会网关?
    31 条回复    2021-11-25 13:14:39 +08:00
    retanoj
        1
    retanoj  
       2021-11-24 16:24:19 +08:00
    感觉不是个 route ,是个 filter
    FanError
        2
    FanError  
       2021-11-24 16:29:13 +08:00
    最近也在学习这方面东东,似乎现在常用的方案是把鉴权直接在网关上做的。

    业务上不做任何鉴权操作
    MeloForsaken
        3
    MeloForsaken  
    OP
       2021-11-24 16:30:09 +08:00
    @retanoj 是的,是我理解错了,但是 filter 里怎么转发到鉴权服务上(不用真正的 ip 和端口)
    sxfscool
        4
    sxfscool  
       2021-11-24 16:30:46 +08:00
    业务不做鉴权,鉴权的信息当成参数传递到子服务
    MeloForsaken
        5
    MeloForsaken  
    OP
       2021-11-24 16:37:33 +08:00
    @sxfscool @FanError 业务和鉴权分开的啊,鉴权是单独的一个服务
    FanError
        6
    FanError  
       2021-11-24 16:44:47 +08:00
    @MeloForsaken 网上的方案全部是在网关上做的,所以不存在转发这个问题

    鉴权通过了,直接到业务模块
    eason1874
        7
    eason1874  
       2021-11-24 16:49:41 +08:00
    什么怎么写,不就写拦截器那样写么,这问题问得太宽泛,很难答。你要问具体哪个语言的怎么说,大家还可以给你推荐一些框架例子

    如果不大懂,干脆用软件方案得了,APISIX 之类的开源 API 网关,带控制台,可以像用云厂商 API 网关服务那样配置
    anonydmer
        8
    anonydmer  
       2021-11-24 16:51:55 +08:00   ❤️ 1
    1. 是认证还是鉴权?两者不一样。认证容易统一处理,但是鉴权视业务需求而定,复杂的鉴权只能是业务方自己做
    2. 不管你是认证还是授权服务独立出来了,参照一楼,应该用 filter 而不是 route ;如果用 route 不是把鉴权服务又做成网关服务了?
    abersheeran
        9
    abersheeran  
       2021-11-24 16:54:59 +08:00
    你是想让鉴权服务提供 RPC ,然后网关去调用吧?
    kifile
        10
    kifile  
       2021-11-24 16:55:49 +08:00
    aop 切面,注解鉴权处理
    abobobo
        11
    abobobo  
       2021-11-24 17:03:04 +08:00
    网关写个 filter ,在网关验证请求头部带的 token , 验证通过后通过服务名转发到业务上(在 gateway 里配置好 服务名称以及匹配规则)
    retanoj
        12
    retanoj  
       2021-11-24 17:26:37 +08:00
    “转发”的意思可以是将 HTTP 请求原封不动的发往另一个目的地
    在这里也可以理解为解析请求,做一些业务逻辑(比如认证检查),再取出一些调用的服务,参数,进行(远程?)服务调用
    nicholasxuu
        13
    nicholasxuu  
       2021-11-24 17:38:28 +08:00
    我们是 envoy 鉴权 filter 在 request 上加个 header (内部不会冲突的 header 名,如果用户传了就删掉),然后业务直接读 header 就行了。
    securityCoding
        14
    securityCoding  
       2021-11-24 17:43:20 +08:00
    这提问也是醉了,至少带个技术栈啊

    如何把到网关的请求都转发到鉴权服务上?
    自定义 filter

    这个 route 得怎么写?
    route 里面配置一下鉴权的 filter

    转发到鉴权服务上的请求
    不用转发,filter 里面请求认证服务

    鉴权后如何再转发到业务上?
    网关本身就是 proxy 角色,不用再次转发

    是重定向到业务服务上?
    接上

    怎么知道端口和 IP ?
    网关里面一般会有目标服务概念. spring-cloud-gateway 是服务注册名,内置默认 filter 自动查询可用节点

    还是再转会网关?
    网关本身就是 proxy


    综上,你需要先把网关涉及的概念弄清楚,再重新组织一下问题
    SuperShuYe
        15
    SuperShuYe  
       2021-11-24 17:47:12 +08:00
    GW 服务(外网):
    gw.abc.com 鉴权后 header 携带 token
    这里配置转发 172.168.0.1 gw.abc.com/order 172.168.0.2 gw.abc.com/user
    Order 服务(内网):
    172.168.0.1 gw.abc.com/order
    User 服务(内网) :
    172.168.0.2 gw.abc.com/user
    Saxton
        16
    Saxton  
       2021-11-24 17:51:57 +08:00
    鉴权中心永远只负责鉴权,逻辑不要搞错了,转发权还是在网关身上,目前我们的系统的是
    请求 -》网关-》鉴权-》 网关-》 转发到对应服务,对应的服务不需要在鉴权了,当然有些系统的架构服务的调用也需要额外的鉴权,网关会签发一个临时的调用 TOKEN 和一个用户 TOKEN 一起转发到对应服务,对应服务在拦截这个 token 鉴别,但其实没必要多做一步,你要做的是完全信任鉴权中心和防火墙
    Saxton
        17
    Saxton  
       2021-11-24 17:55:44 +08:00
    你也没说你的技术栈是什么
    传统的 springcloud 可以直接在 spring-cloud-gateway 上跑鉴权
    但我的做法我喜欢另外跑一个鉴权中心,这个鉴权中心同时还承担了签证责任,网关永远只是一个负责转发的东西,不要把过多的逻辑压在网关身上
    MeloForsaken
        18
    MeloForsaken  
    OP
       2021-11-24 18:54:33 +08:00
    @Saxton 是 springcloud ,没有讲清楚,按你的意思,网关->鉴权->网关,这个得怎么实现?网上没有找到具体的实现方式
    MeloForsaken
        19
    MeloForsaken  
    OP
       2021-11-24 19:10:10 +08:00
    @abersheeran @abobobo @nicholasxuu @securityCoding @eason1874 @anonydmer spring cloud ,打个比方 URL 鉴权,网关和鉴权是两个服务,网关具体怎么去调用? RPC ?把鉴权抽离成公共依赖?还是有什么其他比较好的写法?
    yangyaofei
        20
    yangyaofei  
       2021-11-24 19:35:52 +08:00 via Android
    oauth2?
    wantooo
        21
    wantooo  
       2021-11-24 19:43:31 +08:00
    spring cloud 情况下 request 到网关,自定义 globalFilter 通过 feign 调用鉴权服务,返回结果,决定是继续 chain 还是结束
    qqlyatt
        22
    qqlyatt  
       2021-11-24 20:10:48 +08:00   ❤️ 2
    使用 Java 开发正常的业务流程应该是:1.普通浏览不用登录,用户点击某个特殊的 api 或者按钮需要登录。2.需要登录,前端页面,引导用户跳转进入《认证服务器 Authorization-Server 》的《认证》页面,用户在认证页面输入用户名密码或者手机号验证码,确认用户《身份》。3.确认用户后,《认证服务器》返回给前端授权码 authorization_code ,前端 NodeJS 服务器拿着授权码并组织一次 post 请求,在 POST 请求中携带自身的客户端用户名密码以及 redirect_uri ,这个是在《认证服务器》中注册过的客户端 client ,是把前端应用当作一个外来的客户端。这个 redirect_uri 是用来接收令牌 Token 的。《认证服务器》确认过全段服务器的用户名,密码和授权码,再验证当时注册 client 时填写过的 redirect_uri ,一致后,响应一个带有当前用户《身份权限》信息的 Token 。然后前端 NodeJS 将该 Token 存储起来存哪自己看 cookie,session,redis 。每次该用户调用资源服务的时候,也就是你的业务功能的时候,NodeJS 将他的令牌 Token 拿到,用一个类似过滤器的 func 将每次请求的请求头 Header 都加上 Key:Authorization Value:Bearer Token 值。这个请求可以直接发到网关上,也可以不用网关,直接请求到资源服务里,资源服务也能解析这个 Token 确认用户有没有权限请求这个资源。不过你是用网关的,所以,这个请求发到网关上,然后网关上过滤这个请求 Header ,验证这个用户的权限是否和他请求的资源地址匹配,如果不匹配,做出响应 403 无权限响应。如果匹配那就通过,并转发到资源服务器,获取资源服务器响应。如果你配置了 OAuth2+JWT ,网关过滤这一块不用手敲了,只需要简单的配置几下就行。
    qqlyatt
        23
    qqlyatt  
       2021-11-24 20:12:42 +08:00
    网关上那个过滤请求 Header 的过程就叫做《鉴权》。
    eason1874
        24
    eason1874  
       2021-11-24 22:05:27 +08:00   ❤️ 1
    @MeloForsaken 不是公共依赖,就拦截过滤

    网关->鉴权->网关,这种是把请求转发给 Spring Cloud Gateway 匹配路由执行 Filters ,Filter 把权限信息加在 Headers 之后 Spring Cloud Gateway 再自己把请求转发给业务后端,相当于总共反代两次

    还有一种常见的是类似微服务的形式,鉴权服务不管实际请求,只提供鉴权 HTTP API ,网关收到请求把信息发给鉴权 HTTP API ,拿到权限信息添加到 Headers 转发给后端

    比如用 Nginx + ngx_lua 可以在 rewrite_by_lua 阶段请求鉴权 HTTP API ,把响应的权限信息写入 Nginx 变量,通过 proxy_set_header 传递给后端

    location /openapi/ {
    set $authinfo '';
    rewrite_by_lua_block {
    ... resty.http 请求鉴权内网 HTTP API
    ngx.var.authinfo = 响应的权限信息;
    }
    proxy_set_header "AuthInfo" $authinfo;
    proxy_pass ...请求内网后端的反代配置
    }

    这样后端就可以在 HTTP Header 的 AuthInfo 里取当前用户和权限信息了
    abobobo
        25
    abobobo  
       2021-11-25 08:57:35 +08:00   ❤️ 1
    目前我是鉴权+网关一个服务,认证一个服务,一个 url 如果需要登录( token )才能访问,网关的 filter 会对 url 进行鉴权,成功就转发到指定服务,不成功就返回失败提示。用的是 spring-cloud-gateway 跟 JWT 。
    @MeloForsaken
    Saxton
        26
    Saxton  
       2021-11-25 09:11:14 +08:00
    @abobobo 一大堆 github -》 zhoutaoo/SpringCloud
    Saxton
        27
    Saxton  
       2021-11-25 09:11:51 +08:00   ❤️ 2
    @MeloForsaken @错人了 github-》 /zhoutaoo/SpringCloud
    james2013
        28
    james2013  
       2021-11-25 11:05:34 +08:00
    在网关里先调用鉴权接口,成功网关再转发到对应服务
    转发到业务,明显是网关的活,关鉴权什么事?
    nicholasxuu
        29
    nicholasxuu  
       2021-11-25 11:30:20 +08:00   ❤️ 1
    @MeloForsaken 什么网关?
    envoy 的话,可以用 ext_authz ( https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto ),写个高性能的鉴权 rpc ,envoy 会去调用 rpc ,处理 request ,envoy 再把 request 传给后面的服务。
    jiameng123
        30
    jiameng123  
       2021-11-25 12:03:18 +08:00
    可以使用 openresty 实现,在指定的 location 中 rewrite_by_lua 模块中写 lua 脚本,发子请求,子请求应答回来判断成功后,再继续用该 location 后面的逻辑处理
    chenfcheng
        31
    chenfcheng  
       2021-11-25 13:14:39 +08:00
    apisix 或者 阿里 api gateway 了解下 ? 鉴权都在网关上做了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2923 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 14:58 · PVG 22:58 · LAX 06:58 · JFK 09:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.