Higress(看这一篇就够了)

06-01 1253阅读

目录:

    • 为什么需要服务网关
    • Higress是什么
    • 安装DockerCompose
    • 部署Higress
    • 创建网关微服务模块
    • Higress路由配置
    • Higress策略配置-跨域配置
    • Higress解决如何允许跨域
    • Higress策略配置之什么是HTTP认证
    • Higress策略配置-Basic 认证
    • 什么是JWT认证
    • JWT方式
    • JWT原理
    • 载荷 / Payload
    • 创建认证中心微服务
    • 编写JWT工具类生成jwt
    • 编写JWT工具类解密Token
    • 认证中心微服务颁发Token令牌
    • JWT配置
    • Key 认证
    • 请求屏蔽

      Higress(看这一篇就够了)

      为什么需要服务网关

      传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。

      Higress(看这一篇就够了)

      服务网关的基本功能

      Higress(看这一篇就够了)

      微服务网关的作用:

      • 提供了统一访问入口,降低了服务受攻击面
      • 提供了统一跨域解决方案
      • 提供了统一日志记录操作,可以进行统一监控
      • 提供了统一权限认证支持
      • 提供了微服务限流功能,可以保护微服务,防止雪崩效应发生

        主流网关的对比与选型

        • Kong 网关:Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑
        • Zuul1.x 网关:Zuul 1.0 的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况
        • gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。
        • Higress:一个遵循开源Ingress/Gateway API标准,提供流量调度、服务治理、安全防护三合一的高集成、易使用、易扩展、热更新的下一代云原生网关。

          Higress是什么

          Higress(看这一篇就够了)

          Higress是什么

          Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio + Envoy为核心构建的下一代云原生网关,实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力,深度集成Dubbo、Nacos、Sentinel等微服务技术栈,能够帮助用户极大的降低网关的部署及运维成本且能力不打折。

          Higress(看这一篇就够了)

          传统网关分类

          行业中通常把网关分为两个大类:流量网关与业务网关,流量网关主要提供全局性的、与后端业务无关的策略配置,例如阿里内部的的统一接入网关Tengine就是典型的流量网关;业务网关顾名思义主要提供独立业务域级别的、与后端业务紧耦合策略配置,随着应用架构模式从单体演进到现在的分布式微服务,业务网关也有了新的叫法 - 微服务网关(图示说明如下)。在目前容器技术与K8s主导的云原生时代,下一代网关模式依然是这样吗?

          Higress(看这一篇就够了)

          Higress定位

          在虚拟化时期的微服务架构下,业务通常采用流量网关 + 微服务网关的两层架构,流量网关负责南北向流量调度和安全防护,微服务网关负责东西向流量调度和服务治理,而在容器和 K8s 主导的云原生时代,Ingress 成为 K8s 生态的网关标准,赋予了网关新的使命,使得流量网关 + 微服务网关合二为一成为可能。

          Higress(看这一篇就够了)

          安装DockerCompose

          Higress(看这一篇就够了)

          关闭防火墙

          systemctl stop firewalld
          

          设置安装仓库

          #安装yum的工具包
          yum install -y yum-utils \
                device-mapper-persistent-data \
                lvm2 --skip-broken
          #更新本地镜像源
          # 设置docker镜像源
          yum-config-manager \
            --add-repo \
             https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
            
          sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
          #将软件包信息提前在本地索引缓存,用来提高搜索安装软件的速度,建议执行这个命令可以提升yum安装的速度。
          yum makecache fast
          

          安装docker引擎

          sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
          

          启动docker

          systemctl start docker
          

          设置docker自启动

          systemctl enable docker
          

          测试docker是否安装成功

          docker run hello-world
          

          部署Higress

          Higress(看这一篇就够了)

          搭建Higress

          在安装之前要保证Docker安装成功并且成功安装Docker Copmpose插件。

          curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -c nacos://192.168.47.100:8848 --nacos-username=nacos --nacos-password=nacos -p 
          

          Higress(看这一篇就够了)

          启动成功后,本机端口占用情况如下:

          80端口:Higress 暴露,用于 HTTP 协议代理

          443端口:Higress 暴露,用于 HTTPS 协议代理

          15020端口:Higress 暴露,用于暴露 Prometheus 指标

          8080端口:Higress 控制台 暴露,(admin/123456)

          Higress命令

          Higress(看这一篇就够了)

          命令解释:

          startup.sh : 启动Higress

          shutdown.sh : 停止Higress

          configure.sh : 配置nacos地址

          访问Higress控制台

          在浏览器中输入http://127.0.0.1:8080,使用用户名 admin 和安装时设置的密码登录 Higress 控制台。

          Higress(看这一篇就够了)

          创建网关微服务模块

          创建子模块 jjy-order-higress

          引入依赖包

           
              
                org.springframework.boot
                spring-boot-starter-web
              
              
              
                com.alibaba.cloud
                spring-cloud-starter-alibaba-nacos-discovery
              
          

          编写配置文件

          在resources文件夹下面创建application.yml文件。

          spring:
            application:
            # 应用名字
             name: order-service
            cloud:
             nacos:
              discovery:
              # Nacos注册中心的地址
               server-addr:  192.168.47.100:8848
          server:
            port: 8006
          

          编写主启动类

          在com.jjy文件夹下面创建OrderHigressAppcation主启动类。

          /**
           * 主启动类
           */
          @Slf4j
          @EnableDiscoveryClient
          @SpringBootApplication
          public class OrderAppcation
          {
            public static void main( String[] args )
             {
              SpringApplication.run(OrderAppcation.class,args);
              log.info("****************** 订单微服务启动成功 ***********");
             }
          }
          

          编写测试控制器

          package com.jjy.controller;
          import org.springframework.web.bind.annotation.GetMapping;
          import org.springframework.web.bind.annotation.RestController;
          @RestController
          public class IndexController {
            @GetMapping("/index")
            public String index(){
              return "hello  higress";
             }
          }
          

          Higress路由配置

          Higress(看这一篇就够了)

          什么是路由

          在微服务架构中,路由是一种用于管理和定向请求流量的重要机制。微服务架构将一个应用程序拆分成一组小型、独立的服务,每个服务专注于执行特定的业务功能。路由在这样的环境中起到了指导请求流向的作用。

          Higress(看这一篇就够了)

          安装Switchhosts

          SwitchHosts是一款便捷且免费的软件,体积为8M左右,不会占用电脑过多的内存,并且默认就是绿色软件,带有简体中文界面,在windows7、xp与vista等系统中能够运行。

          该软件主要带有两个功能:

          切换hosts与编辑hosts。

          Higress(看这一篇就够了)

          设置域名

          Higress(看这一篇就够了)

          创建路由

          配置支付服务路由规则。

          Higress(看这一篇就够了)

          设置路由策略

          Higress(看这一篇就够了)

          重写地址

          Higress(看这一篇就够了)

          请求验证

          执行以下命令,验证测试路由可以正常工作:

          # should output a JSON object containing request data 
          curl http://www.it.com/payment/index
          

          Higress策略配置-跨域配置

          为什么会出现跨域问题

          出于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

          什么是跨域

          当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

          当前页面url被请求页面url是否跨域原因
          http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
          http://www.test.com/https://www.test.com/index.html跨域协议不同(http/https)
          http://www.test.com/http://www.baidu.com/跨域主域名不同(test/baidu)
          http://www.test.com/http://blog.test.com/跨域子域名不同(www/blog)
          http://www.test.com:8080/http://www.test.com:7001/跨域端口号不同(8080/7001)

          跨域问题演示

          在resources中创建templates文件夹,在编写index页面

          
          
            
            Title
          
          
          
          
          
            $.get("http://www.it.com/order/index",function(data,status){
              alert("Data: " + data );
             });
          
          
          

          Higress解决如何允许跨域

          CORS

          • 如何允许跨域,一种解决方法就是目的域告诉请求者允许什么来源域来请求,那么浏览器就会知道B域是否允许A域发起请求。
          • CORS(“跨域资源共享”(Cross-origin resource sharing))就是这样一种解决手段。

            CORS使得浏览器在向目的域发起请求之前先发起一个OPTIONS方式的请求到目的域获取目的域的信息,比如获取目的域允许什么域来请求的信息。

            Higress策略配置之什么是HTTP认证

            概述

            HTTP认证是一种用于保护Web应用程序的一种身份验证机制。它通过在HTTP请求的头部添加认证信息,来验证用户的身份和权限。HTTP认证可以用于保护敏感信息,限制访问某些资源,或者在访问某些操作之前要求用户提供凭据。

            HTTP 基本认证

            常见的验证方案包括

            1、Basic Authentication(基本认证)

            Basic认证是最常见的HTTP认证方式之一。在Basic认证中,客户端发送请求时,会在请求头中包含一个"Authorization"字段,该字段包含了经过Base64编码的用户名和密码。

            2、Digest Authentication(摘要认证)

            Digest认证是一种更安全的认证方式。在Digest认证中,服务器会向客户端发送一个随机数(称为"nonce"),客户端根据该随机数和用户密码计算一个摘要,并将其发送给服务器。服务器收到摘要后,会验证其有效性。Digest认证相对于Basic认证而言,更难以被中间人攻击截获密码。

            3、Bearer Token Authentication(令牌认证)

            Bearer认证是一种使用令牌(Token)进行身份验证的方式。在Bearer认证中,客户端在请求头中添加一个"Authorization"字段,该字段包含了一个令牌信息。服务器在接收到请求后,会验证令牌的有效性,并根据令牌来识别用户身份。

            4、OAuth(开放授权)

            OAuth认证是一种开放标准的身份验证协议,用于授权第三方应用程序访问用户资源。在OAuth认证中,用户可以通过授权服务器授权第三方应用程序访问自己的资源。这种方式可以避免用户将密码直接提供给第三方应用程序。

            Higress策略配置-Basic 认证

            Higress(看这一篇就够了)

            Basic 概述

            Basic 认证是HTTP 中非常简单的认证方式,因为简单,所以不是很安全,不过仍然非常常用。当一个客户端向一个需要认证的HTTP服务器进行数据请求时,,HTTP服务器会返回401状态码,要求客户端输入用户名和密码。用户输入用户名和密码后,用户名和密码会经过BASE64加密附加到请求信息中再次请求HTTP服务器,HTTP服务器会根据请求头携带的认证信息,决定是否认证成功及做出相应的响应。

            Higress(看这一篇就够了)

            功能说明

            basic-auth插件实现了基于 HTTP Basic Auth 标准进行认证鉴权的功能

            配置字段

            全局配置

            名称数据类型填写要求默认值描述
            consumersarray of object必填-配置服务的调用者,用于对请求进行认证
            global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

            consumers中每一项的配置字段说明如下:

            名称数据类型填写要求默认值描述
            credentialstring必填-配置该consumer的访问凭证
            namestring必填-配置该consumer的名称

            域名和路由级配置

            名称数据类型填写要求默认值描述
            allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

            注意:

            • 对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

              配置示例

              1、对特定路由或域名开启认证和鉴权

              以下配置将对网关特定路由或域名开启 Basic Auth 认证和鉴权,注意凭证信息中的用户名和密码之间使用":"分隔,credential字段不能重复。

              全局配置

              consumers:
              - credential: 'admin:123456'
                name: consumer1
              - credential: 'guest:abc'
                name: consumer2
              global_auth: false
              

              路由级配置

              对 route-a 和 route-b 这两个路由做如下配置:

              allow: 
              - consumer1
              

              若是在控制台进行配置,此例指定的 route-a 和 route-b 即在控制台创建路由时填写的路由名称,当匹配到这两个路由时,将允许name为consumer1的调用者访问,其他调用者不允许访问;此例指定的 *.example.com 和 test.com 用于匹配请求的域名,当发现域名匹配时,将允许name为consumer2的调用者访问,其他调用者不允许访问。

              测试配置

              Higress(看这一篇就够了)

              相关错误码

              HTTP 状态码出错信息原因说明
              401Request denied by Basic Auth check. No Basic Authentication information found.请求未提供凭证
              401Request denied by Basic Auth check. Invalid username and/or password请求凭证无效
              403Request denied by Basic Auth check. Unauthorized consumer请求的调用方无访问权限

              什么是JWT认证

              JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。官方网址https://jwt.io/

              传统的session认证

              Session 的认证流程通常会像这样:

              Higress(看这一篇就够了)

              缺点:

              安全性:CSRF攻击因为基于cookie来进行用户识别, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

              扩展性:对于分布式应用,需要实现 session 数据共享

              性能:每一个用户经过后端应用认证之后,后端应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大,与REST风格不匹配。因为它在一个无状态协议里注入了状态。

              JWT方式

              Higress(看这一篇就够了)

              优点:

              • 无状态
              • 适合移动端应用
              • 单点登录友好

                JWT原理

                JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样

                {
                  "姓名": "张三",
                  "角色": "管理员",
                  "到期时间": "2030年7月1日0点0分"
                }
                

                注意:

                用户与服务端通信的时候,都要发回这个 JSON

                对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候会加上签名,服务器就不保存任何 session

                数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

                JWT 结构

                一个 JWT 实际上就是一个字符串,它由三部分组成:头部、载荷与签名。中间用点 . 分隔成三个部分。注意 JWT 内部是没有换行的。

                Higress(看这一篇就够了)

                头部 / header

                JSON对象,描述 JWT 的元数据。其中 alg 属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ 属性表示这个令牌(token)的类型(type),统一写为 JWT。

                {
                 "alg": "HS256",
                 "typ": "JWT"
                }
                

                注意:

                上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT然后将头部进行Base64编码构成了第一部分,Base64是一种用64个字符来表示任意二进制数据的方法,Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。

                载荷 / Payload

                Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 指定七个默认字段供选择。除了默认字段之外,你完全可以添加自己想要的任何字段,一般用户登录成功后,就将用户信息存放在这里

                iss:发行人
                exp:到期时间
                sub:主题
                aud:用户
                nbf:在此之前不可用
                iat:发布时间
                jti:JWT ID用于标识该JWT
                
                {
                 "iss": "xxxxxxx",
                 "sub": "xxxxxxx",
                 "aud": "xxxxxxx",
                 "user": {
                     'username': 'itbaizhan',
                     'userId': 1
                  } 
                }
                

                签名 / Signature

                • 签名部分是对上面的 头部、载荷 两部分数据进行的数据签名
                • 为了保证数据不被篡改,则需要指定一个密钥,而这个密钥一般只有你知道,并且存放在服务端
                • 生成签名的代码一般如下:
                  // 其中secret 是密钥
                  String signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
                  

                  JWT 的使用方式

                  Higress(看这一篇就够了)

                  流程:

                  客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在

                  localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie

                  里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

                  创建认证中心微服务

                  认证微服务模块

                  引入依赖

                      
                        org.springframework.boot
                        spring-boot-starter-web
                      
                      
                        com.alibaba.cloud
                        spring-cloud-starter-alibaba-nacos-discovery
                      
                      
                        org.bitbucket.b_c
                        jose4j
                        0.7.0
                      
                      
                        cn.hutool
                        hutool-all
                        5.8.18
                      
                    
                  

                  创建配置文件

                  在resources文件夹下面创建application.yml文件。

                  spring:
                    application:
                    # 应用名字
                     name: auth-service
                    cloud:
                     nacos:
                      discovery:
                      # Nacos注册中心的地址
                       server-addr:  192.168.47.100:8848
                  server:
                    port: 8989
                  

                  创建主启动类

                  @SpringBootApplication
                  @Slf4j
                  public class AuthApplication
                  {
                    public static void main( String[] args ) throws JoseException {
                      SpringApplication.run(AuthApplication.class,args);
                      log.info("*****************  认证授权中心启动成功 **************");
                     }
                  }
                  

                  编写JWT工具类生成jwt

                  引入依赖

                     org.bitbucket.b_c
                     jose4j
                     0.7.0
                  
                  

                  生成公钥和私钥

                  RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
                      final String publicKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
                      final String privateKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);
                      System.out.println(publicKeyString);
                      System.out.println(privateKeyString);
                  

                  生成token

                   // 创建claims,这将是JWT的内容 B部分
                      JwtClaims claims = new JwtClaims();
                      // 谁创建了令牌并签署了它
                      claims.setIssuer("abcd");
                      // 令牌将被发送给谁
                      claims.setAudience("Audience");
                      // 令牌失效的时间长(从现在开始10分钟)
                      claims.setExpirationTimeMinutesInTheFuture(10);
                      // 令牌的唯一标识符
                      claims.setGeneratedJwtId();
                      // 当令牌被发布/创建时(现在)
                      claims.setIssuedAtToNow();
                      // 在此之前,令牌无效(2分钟前)
                      claims.setNotBeforeMinutesInThePast(2);
                      // 主题 ,是令牌的对象
                      claims.setSubject("subject");
                      // 可以添加关于主题的附加 声明/属性
                      claims.setClaim("userId", userId);
                      claims.setClaim("username", username);
                      // JWT是一个JWS和/或一个带有JSON声明的JWE作为有效负载。
                      // 在这个例子中,它是一个JWS,所以我们创建一个JsonWebSignature对象。
                      JsonWebSignature jws = new JsonWebSignature();
                      // JWS的有效负载是JWT声明的JSON内容
                      jws.setPayload(claims.toJson());
                      System.out.println(claims.toJson());
                      PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privatekey)).getPrivateKey();
                      // JWT使用私钥签署
                      jws.setKey(privateKey);
                      /*
                       * 设置关键ID(kid)头,因为这是一种礼貌的做法。 在这个例子中,我们只有一个键但是使用键ID可以帮助
                       * 促进平稳的关键滚动过程
                       */
                      jws.setKeyIdHeaderValue("keyId");
                      // 在jw/jws上设置签名算法,该算法将完整性保护声明
                      jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
                      /*
                       * 签署JWS并生成紧凑的序列化或完整的jw/JWS 表示,它是由三个点('.')分隔的字符串
                       * 在表单头.payload.签名中使用base64url编码的部件 如果你想对它进行加密,你可以简单地将这个jwt设置为有效负载
                       * 在JsonWebEncryption对象中,并将cty(内容类型)头设置为“jwt”。
                       */
                      String jwt = jws.getCompactSerialization();
                      // 现在你可以用JWT做点什么了。比如把它寄给其他的派对
                      // 越过云层,穿过网络。
                      System.out.println("JWT: " + jwt);
                      return jwt;
                  

                  编写JWT工具类解密Token

                  public static void checkJwt(String jwt) throws MalformedClaimException, JoseException {
                      /*
                       * 使用JwtConsumer builder构建适当的JwtConsumer,它将 用于验证和处理JWT。 JWT的具体验证需求是上下文相关的, 然而,
                       * 通常建议需要一个(合理的)过期时间,一个受信任的时间 发行人, 以及将你的系统定义为预期接收者的受众。
                       * 如果JWT也被加密,您只需要提供一个解密密钥对构建器进行解密密钥解析器。
                       */
                      PublicKey publicKey1 = new RsaJsonWebKey(JsonUtil.parseJson(publicKey)).getRsaPublicKey();
                      JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime()
                           .setAllowedClockSkewInSeconds(30) // 允许在验证基于时间的令牌时留有一定的余地,以计算时钟偏差。单位/秒
                           .setRequireSubject() // 主题声明
                           .setExpectedIssuer("Issuer") // JWT需要由谁来发布,用来验证 发布人
                           .setExpectedAudience("Audience") // JWT的目的是给谁, 用来验证观众
                           .setVerificationKey(publicKey1) // 用公钥验证签名 ,验证秘钥
                           .setJwsAlgorithmConstraints( // 只允许在给定上下文中预期的签名算法,使用指定的算法验证
                              new AlgorithmConstraints(ConstraintType.WHITELIST, // 白名单
                                  AlgorithmIdentifiers.RSA_USING_SHA256))
                           .build(); // 创建JwtConsumer实例
                      try {
                        // 验证JWT并将其处理为jwtClaims
                        JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt);
                  //          如果JWT失败的处理或验证,将会抛出InvalidJwtException。
                  //          希望能有一些有意义的解释(s)关于哪里出了问题。
                        System.out.println("JWT validation succeeded! " + jwtClaims);
                       } catch (InvalidJwtException e) {
                        System.out.println("Invalid JWT! " + e);
                        // 对JWT无效的(某些)特定原因的编程访问也是可能的
                        // 在某些情况下,您是否需要不同的错误处理行为。
                        // JWT是否已经过期是无效的一个常见原因
                        if (e.hasExpired()) {
                          System.out.println("JWT expired at " + e.getJwtContext().getJwtClaims().getExpirationTime());
                         }
                        // 或者观众是无效的
                        if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID)) {
                          System.out.println("JWT had wrong audience: " + e.getJwtContext().getJwtClaims().getAudience());
                         }
                       }
                     }
                  

                  认证中心微服务颁发Token令牌

                  编写认证中心控制器

                  创建controller包,在controller里面新建AuthController接口。

                  @RestController
                  public class AuthController {
                    @Autowired
                    SysLoginService sysLoginService;
                    @PostMapping("login")
                    public R login(@RequestBody LoginBody form) throws MalformedClaimException, JoseException {
                      return sysLoginService.login(form.getUsername(), form.getPassword());
                     }
                  }
                  

                  编写统一结果返回集

                  package com.jjy.domian;
                  import lombok.AllArgsConstructor;
                  import lombok.Data;
                  import lombok.NoArgsConstructor;
                  import lombok.ToString;
                  /**
                   * 统一结果返回集
                   */
                  @Data
                  @AllArgsConstructor
                  @NoArgsConstructor
                  @ToString
                  public class R {
                    // 状态码
                    private int code;
                    // 返回信息
                    private String meg;
                    // 数据
                    private Object data;
                    public static R fail(String meg){
                      R r = new R();
                      r.setCode(500);
                      r.setMeg(meg);
                      return r;
                     }
                    public static R ok(Object data){
                      R r = new R();
                      r.setCode(200);
                      r.setMeg("sucess");
                      r.setData(data);
                      return r;
                     }
                  }
                  

                  登录业务层

                  package com.jjy.service;
                  import com.alibaba.nacos.common.utils.StringUtils;
                  import com.itbaizhan.domian.LoginBodyDTO;
                  import com.itbaizhan.domian.R;
                  import com.itbaizhan.utils.JwtUtils;
                  import org.jose4j.lang.JoseException;
                  import org.springframework.stereotype.Service;
                  @Service
                  public class SysLoginService {
                  
                    /**
                     * 登录
                     * @param loginBodyDTO
                     * @return
                     */
                    public R login(LoginBodyDTO loginBodyDTO) throws JoseException {
                      // 1、用户名或者密码校验
                      if (StringUtils.isEmpty(loginBodyDTO.getUsername()) || StringUtils.isEmpty(loginBodyDTO.getPassword()) ){
                        return R.fail("用户名或者密码为空");
                       }
                      // 2、判断用户名和密码是否正确
                      //TODO 数据库操作
                      if (loginBodyDTO.getUsername().equals("admin")&& loginBodyDTO.getPassword().equals("123456")){
                        // 颁发登录token
                        String token = JwtUtils.sign(1001L, "admin");
                        return R.ok(token);
                       }else {
                        return R.fail("用户名或者密码不对");
                       }
                     }
                  }
                  

                  JWT配置

                  Higress(看这一篇就够了)

                  基于Token的认证

                  很多对外开放的API需要识别请求者的身份,并据此判断所请求的资源是否可以返回给请求者。token就是一种用于身份验证的机制,基于这种机制,应用不需要在服务端保留用户的认证信息或者会话信息,可实现无状态、分布式的Web应用授权,为应用的扩展提供了便利。

                  Higress(看这一篇就够了)

                  业务流程:

                  1.客户端向API网关发起认证请求,请求中一般会携带终端用户的用户名和密码;

                  2.网关将请求直接转发给后端服务;

                  3.后端服务读取请求中的验证信息(比如用户名、密码)进行验证,验证通过后使用私钥生成标准的token,返回给网关;

                  4.网关将携带token的应答返回给客户端,客户端需要将这个token缓存到本地;

                  5.客户端向API网关发送业务请求,请求中携带token;

                  6.网关使用用户设定的公钥对请求中的token进行验证,验证通过后,将请求透传给后端服务;

                  7.后端服务进行业务处理后应答;

                  8.网关将业务应答返回给客户端。

                  功能说明

                  jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能,支持从HTTP请求的URL参数、请求头、Cookie字段解析JWT,同时验证该Token是否有权限访问。

                  配置字段

                  全局配置

                  名称数据类型填写要求默认值描述
                  consumersarray of object必填-配置服务的调用者,用于对请求进行认证
                  global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

                  consumers中每一项的配置字段说明如下:

                  名称数据类型填写要求默认值描述
                  namestring必填-配置该consumer的名称
                  jwksstring必填-https://www.rfc-editor.org/rfc/rfc7517 指定的json格式字符串,是由验证JWT中签名的公钥(或对称密钥)组成的Json Web Key Set
                  issuerstring必填-JWT的签发者,需要和payload中的iss字段保持一致
                  claims_to_headersarray of object选填-抽取JWT的payload中指定字段,设置到指定的请求头中转发给后端
                  from_headersarray of object选填[{“name”:“Authorization”,“value_prefix”:"Bearer "}]从指定的请求头中抽取JWT
                  from_paramsarray of string选填access_token从指定的URL参数中抽取JWT
                  from_cookiesarray of string选填-从指定的cookie中抽取JWT
                  clock_skew_secondsnumber选填60校验JWT的exp和iat字段时允许的时钟偏移量,单位为秒
                  keep_tokenbool选填true转发给后端时是否保留JWT

                  注意:

                  只有当from_headers,from_params,from_cookies均未配置时,才会使用默认值

                  from_headers 中每一项的配置字段说明如下:

                  名称数据类型填写要求默认值描述
                  namestring必填-抽取JWT的请求header
                  value_prefixstring必填-对请求header的value去除此前缀,剩余部分作为JWT

                  claims_to_headers 中每一项的配置字段说明如下:

                  名称数据类型填写要求默认值描述
                  claimstring必填-JWT
                  headerstring必填-从payload取出字段的值设置到这个请求头中,转发给后端
                  overridebool选填truetrue时,存在同名请求头会进行覆盖;false时,追加同名请求头

                  域名和路由级配置

                  名称数据类型填写要求默认值描述
                  allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

                  注意:

                  对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

                  配置示例

                  1、配置全局策略

                  在插件市场中找到JWT Auth进行策略配置。

                  consumers:
                  - issuer: "abcd"
                    jwks: |
                     {
                      "keys": [
                      {
                         "kty": "RSA",
                         "n": "u8SyxKf2kLkmOKOU-mcbXQmacQDCPtxfMGKzYx6HWaGcCFbIrFDubGIWhe3GRP5uQqXekqwDtiqurdGfUzOLSSLfe7bmCmEgntNbF9bgk8lZUhzszmb4sGk6VK4YiOiTWGYWn_7jyKyF_OXEpXY4C3WWWsZwQfLPNUYfVZE76o1MXT9F3622RhLSPOFVqJYL6RlzllvNc2PdfzVEBnFU4wKszT0n9J8ZrNAnlNUxOXi7Y78fLqQks60ERznZwytwB8krydQGkjH9y9pf70QFJW228mUxXHnPhG87Gi2eE62TardkBCvQcm4TJlEB5dnmhFYFhRkAR6IznUAjtkFZIw",
                         "e": "AQAB",
                         "use": "sig",
                         "kid": "keyId",
                         "alg": "RS256"
                       }
                      ]
                     }
                    name: "consumer1"
                  global_auth: false
                  

                  2、配置路由级别

                  开启order-service微服务权限认证。

                  allow:
                  - "consumer1"
                  

                  测试认证中心

                  1、生成用户登录token令牌

                  Higress(看这一篇就够了)

                  2、测试token令牌

                  Higress(看这一篇就够了)

                  Key 认证

                  Higress(看这一篇就够了)

                  功能说明

                  key-auth插件实现了基于 API Key 进行认证鉴权的功能,支持从 HTTP 请求的 URL 参数或者请求头解析 API Key,同时验证该 API Key 是否有权限访问。

                  配置字段

                  全局配置

                  名称数据类型填写要求默认值描述
                  consumersarray of object必填-配置服务的调用者,用于对请求进行认证
                  keysarray of string必填-API Key 的来源字段名称,可以是 URL 参数或者 HTTP 请求头名称
                  in_queryboolin_query 和 in_header 至少有一个为 truetrue配置 true 时,网关会尝试从 URL 参数中解析 API Key
                  in_headerboolin_query 和 in_header 至少有一个为 truetrue配置 true 时,网关会尝试从 HTTP 请求头中解析 API Key
                  global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

                  consumers中每一项的配置字段说明如下:

                  名称数据类型填写要求默认值描述
                  credentialstring必填-配置该consumer的访问凭证
                  namestring必填-配置该consumer的名称

                  域名和路由级配置

                  名称数据类型填写要求默认值描述
                  allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名

                  注意:

                  对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

                  配置示例

                  1、对特定路由或域名开启

                  以下配置将对网关特定路由或域名开启 Key Auth 认证和鉴权,注意credential字段不能重复

                  全局配置

                  consumers:
                  - credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5
                    name: consumer1
                  - credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35
                    name: consumer2
                  keys:
                  - apikey
                  in_query: true
                  global_auth: false
                  

                  路由级配置

                  对 route-a 和 route-b 这两个路由做如下配置:

                  allow: 
                  - consumer1
                  - ```
                  对 *.exmaple.com 和 test.com 在这两个域名做如下配置:
                  ```yml
                  allow:
                  - consumer2
                  

                  请求未提供 API Key,返回401

                  curl  http://xxx.hello.com/test
                  

                  相关错误码

                  HTTP 状态码出错信息原因说明
                  401No API key found in request请求未提供 API Key
                  401Request denied by Key Auth check. Invalid API key不允许当前 API Key 访问
                  403Request denied by Basic Auth check. Unauthorized consumer请求的调用方无访问权限

                  请求屏蔽

                  Higress(看这一篇就够了)

                  功能说明

                  request-block插件实现了基于 URL、请求头等特征屏蔽 HTTP 请求,可以用于防护部分站点资源不对外部暴露。

                  配置字段

                  名称数据类型填写要求默认值描述
                  block_urlsarray of string选填,block_urls,block_headers,block_bodies 中至少必填一项-配置用于匹配需要屏蔽 URL 的字符串
                  block_headersarray of string选填,block_urls,block_headers,block_bodies 中至少必填一项-配置用于匹配需要屏蔽请求 Header 的字符串
                  block_bodiesarray of string选填,block_urls,block_headers,block_bodies 中至少必填一项-配置用于匹配需要屏蔽请求 Body 的字符串
                  blocked_codenumber选填403配置请求被屏蔽时返回的 HTTP 状态码
                  blocked_messagestring选填-配置请求被屏蔽时返回的 HTTP 应答 Body
                  case_sensitivebool选填true配置匹配时是否区分大小写,默认区分

                  配置示例

                  1、屏蔽请求 url 路径

                  block_urls:
                  - swagger.html
                  - foo=bar
                  case_sensitive: false
                  

                  根据该配置,下列请求将被禁止访问:

                  curl http://example.com?foo=Bar
                  curl http://exmaple.com/Swagger.html
                  

                  2、屏蔽请求 header

                  block_headers:
                  - example-key
                  - example-value
                  

                  根据该配置,下列请求将被禁止访问:

                  curl http://example.com -H 'example-key: 123'
                  curl http://exmaple.com -H 'my-header: example-value'
                  

                  3、屏蔽请求 body

                  block_bodies:
                  - "hello world"
                  case_sensitive: false
                  

                  根据该配置,下列请求将被禁止访问:

                  curl http://example.com -d 'Hello World'
                  curl http://exmaple.com -d 'hello world'
                  

                  如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力

                  Higress(看这一篇就够了)

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码