8.15日学习打卡---Spring Cloud Alibaba(三)
8.15日学习打卡
目录:
- 8.15日学习打卡
- 为什么需要服务网关
- Higress是什么
- 安装DockerCompose
- 部署Higress
- 创建网关微服务模块
- Higress路由配置
- Higress策略配置-跨域配置
- Higress解决如何允许跨域
- Higress策略配置之什么是HTTP认证
- Higress策略配置-Basic 认证
- 什么是JWT认证
- JWT方式
- JWT原理
- 载荷 / Payload
- 创建认证中心微服务
- 编写JWT工具类生成jwt
- 编写JWT工具类解密Token
- 认证中心微服务颁发Token令牌
- JWT配置
- Key 认证
- 请求屏蔽
为什么需要服务网关
传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。
服务网关的基本功能
微服务网关的作用:
- 提供了统一访问入口,降低了服务受攻击面
- 提供了统一跨域解决方案
- 提供了统一日志记录操作,可以进行统一监控
- 提供了统一权限认证支持
- 提供了微服务限流功能,可以保护微服务,防止雪崩效应发生
主流网关的对比与选型
- Kong 网关:Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑
- Zuul1.x 网关:Zuul 1.0 的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况
- gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。
- Higress:一个遵循开源Ingress/Gateway API标准,提供流量调度、服务治理、安全防护三合一的高集成、易使用、易扩展、热更新的下一代云原生网关。
Higress是什么
Higress是什么
Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio + Envoy为核心构建的下一代云原生网关,实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力,深度集成Dubbo、Nacos、Sentinel等微服务技术栈,能够帮助用户极大的降低网关的部署及运维成本且能力不打折。
传统网关分类
行业中通常把网关分为两个大类:流量网关与业务网关,流量网关主要提供全局性的、与后端业务无关的策略配置,例如阿里内部的的统一接入网关Tengine就是典型的流量网关;业务网关顾名思义主要提供独立业务域级别的、与后端业务紧耦合策略配置,随着应用架构模式从单体演进到现在的分布式微服务,业务网关也有了新的叫法 - 微服务网关(图示说明如下)。在目前容器技术与K8s主导的云原生时代,下一代网关模式依然是这样吗?
Higress定位
在虚拟化时期的微服务架构下,业务通常采用流量网关 + 微服务网关的两层架构,流量网关负责南北向流量调度和安全防护,微服务网关负责东西向流量调度和服务治理,而在容器和 K8s 主导的云原生时代,Ingress 成为 K8s 生态的网关标准,赋予了网关新的使命,使得流量网关 + 微服务网关合二为一成为可能。
安装DockerCompose
关闭防火墙
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.reposed -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
在安装之前要保证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 <你的密码>
启动成功后,本机端口占用情况如下:
80端口:Higress 暴露,用于 HTTP 协议代理
443端口:Higress 暴露,用于 HTTPS 协议代理
15020端口:Higress 暴露,用于暴露 Prometheus 指标
8080端口:Higress 控制台 暴露,(admin/123456)
Higress命令
命令解释:
startup.sh : 启动Higress
shutdown.sh : 停止Higress
configure.sh : 配置nacos地址
访问Higress控制台
在浏览器中输入http://127.0.0.1:8080,使用用户名 admin 和安装时设置的密码登录 Higress 控制台。
创建网关微服务模块
创建子模块 jjy-order-higress
引入依赖包
<!-- springboot依赖包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos依赖包 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
编写配置文件
在resources文件夹下面创建application.yml文件。
spring:application:# 应用名字name: order-servicecloud: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路由配置
什么是路由
在微服务架构中,路由是一种用于管理和定向请求流量的重要机制。微服务架构将一个应用程序拆分成一组小型、独立的服务,每个服务专注于执行特定的业务功能。路由在这样的环境中起到了指导请求流向的作用。
安装Switchhosts
SwitchHosts是一款便捷且免费的软件,体积为8M左右,不会占用电脑过多的内存,并且默认就是绿色软件,带有简体中文界面,在windows7、xp与vista等系统中能够运行。
该软件主要带有两个功能:
切换hosts与编辑hosts。
设置域名
创建路由
配置支付服务路由规则。
设置路由策略
重写地址
请求验证
执行以下命令,验证测试路由可以正常工作:
# 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页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body></body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>$.get("http://www.it.com/order/index",function(data,status){alert("Data: " + data );});
</script>
</html>
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 认证
Basic 概述
Basic 认证是HTTP 中非常简单的认证方式,因为简单,所以不是很安全,不过仍然非常常用。当一个客户端向一个需要认证的HTTP服务器进行数据请求时,,HTTP服务器会返回401状态码,要求客户端输入用户名和密码。用户输入用户名和密码后,用户名和密码会经过BASE64加密附加到请求信息中再次请求HTTP服务器,HTTP服务器会根据请求头携带的认证信息,决定是否认证成功及做出相应的响应。
功能说明
basic-auth插件实现了基于 HTTP Basic Auth 标准进行认证鉴权的功能
配置字段
全局配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
consumers | array of object | 必填 | - | 配置服务的调用者,用于对请求进行认证 |
global_auth | bool | 选填 | - | 若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制) |
consumers中每一项的配置字段说明如下:
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
credential | string | 必填 | - | 配置该consumer的访问凭证 |
name | string | 必填 | - | 配置该consumer的名称 |
域名和路由级配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
allow | array 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
的调用者访问,其他调用者不允许访问。
测试配置
相关错误码
HTTP 状态码 | 出错信息 | 原因说明 |
---|---|---|
401 | Request denied by Basic Auth check. No Basic Authentication information found. | 请求未提供凭证 |
401 | Request denied by Basic Auth check. Invalid username and/or password | 请求凭证无效 |
403 | Request denied by Basic Auth check. Unauthorized consumer | 请求的调用方无访问权限 |
什么是JWT认证
JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。官方网址https://jwt.io/
传统的session认证
Session 的认证流程通常会像这样:
缺点:
安全性:CSRF攻击因为基于cookie来进行用户识别, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
扩展性:对于分布式应用,需要实现 session 数据共享
性能:每一个用户经过后端应用认证之后,后端应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大,与REST风格不匹配。因为它在一个无状态协议里注入了状态。
JWT方式
优点:
- 无状态
- 适合移动端应用
- 单点登录友好
JWT原理
JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样
{"姓名": "张三","角色": "管理员","到期时间": "2030年7月1日0点0分"
}
注意:
用户与服务端通信的时候,都要发回这个 JSON
对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候会加上签名,服务器就不保存任何 session
数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。
JWT 结构
一个 JWT 实际上就是一个字符串,它由三部分组成:头部、载荷与签名。中间用点 . 分隔成三个部分。注意 JWT 内部是没有换行的。
头部 / 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 的使用方式
流程:
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在
localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie
里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization
字段里面。
创建认证中心微服务
认证微服务模块
引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.bitbucket.b_c</groupId><artifactId>jose4j</artifactId><version>0.7.0</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.18</version></dependency></dependencies>
创建配置文件
在resources文件夹下面创建application.yml文件。
spring:application:# 应用名字name: auth-servicecloud: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
引入依赖
<dependency><groupId>org.bitbucket.b_c</groupId><artifactId>jose4j</artifactId><version>0.7.0</version>
</dependency>
生成公钥和私钥
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并将其处理为jwtClaimsJwtClaims 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 {@AutowiredSysLoginService 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")){// 颁发登录tokenString token = JwtUtils.sign(1001L, "admin");return R.ok(token);}else {return R.fail("用户名或者密码不对");}}}
JWT配置
基于Token的认证
很多对外开放的API需要识别请求者的身份,并据此判断所请求的资源是否可以返回给请求者。token就是一种用于身份验证的机制,基于这种机制,应用不需要在服务端保留用户的认证信息或者会话信息,可实现无状态、分布式的Web应用授权,为应用的扩展提供了便利。
业务流程:
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是否有权限访问。
配置字段
全局配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
consumers | array of object | 必填 | - | 配置服务的调用者,用于对请求进行认证 |
global_auth | bool | 选填 | - | 若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制) |
consumers中每一项的配置字段说明如下:
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
name | string | 必填 | - | 配置该consumer的名称 |
jwks | string | 必填 | - | https://www.rfc-editor.org/rfc/rfc7517 指定的json格式字符串,是由验证JWT中签名的公钥(或对称密钥)组成的Json Web Key Set |
issuer | string | 必填 | - | JWT的签发者,需要和payload中的iss字段保持一致 |
claims_to_headers | array of object | 选填 | - | 抽取JWT的payload中指定字段,设置到指定的请求头中转发给后端 |
from_headers | array of object | 选填 | [{“name”:“Authorization”,“value_prefix”:"Bearer "}] | 从指定的请求头中抽取JWT |
from_params | array of string | 选填 | access_token | 从指定的URL参数中抽取JWT |
from_cookies | array of string | 选填 | - | 从指定的cookie中抽取JWT |
clock_skew_seconds | number | 选填 | 60 | 校验JWT的exp和iat字段时允许的时钟偏移量,单位为秒 |
keep_token | bool | 选填 | true | 转发给后端时是否保留JWT |
注意:
只有当from_headers,from_params,from_cookies均未配置时,才会使用默认值
from_headers 中每一项的配置字段说明如下:
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
name | string | 必填 | - | 抽取JWT的请求header |
value_prefix | string | 必填 | - | 对请求header的value去除此前缀,剩余部分作为JWT |
claims_to_headers 中每一项的配置字段说明如下:
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
claim | string | 必填 | - | JWT |
header | string | 必填 | - | 从payload取出字段的值设置到这个请求头中,转发给后端 |
override | bool | 选填 | true | true时,存在同名请求头会进行覆盖;false时,追加同名请求头 |
域名和路由级配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
allow | array 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令牌
2、测试token令牌
Key 认证
功能说明
key-auth
插件实现了基于 API Key 进行认证鉴权的功能,支持从 HTTP 请求的 URL 参数或者请求头解析 API Key,同时验证该 API Key 是否有权限访问。
配置字段
全局配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
consumers | array of object | 必填 | - | 配置服务的调用者,用于对请求进行认证 |
keys | array of string | 必填 | - | API Key 的来源字段名称,可以是 URL 参数或者 HTTP 请求头名称 |
in_query | bool | in_query 和 in_header 至少有一个为 true | true | 配置 true 时,网关会尝试从 URL 参数中解析 API Key |
in_header | bool | in_query 和 in_header 至少有一个为 true | true | 配置 true 时,网关会尝试从 HTTP 请求头中解析 API Key |
global_auth | bool | 选填 | - | 若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制) |
consumers中每一项的配置字段说明如下:
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
credential | string | 必填 | - | 配置该consumer的访问凭证 |
name | string | 必填 | - | 配置该consumer的名称 |
域名和路由级配置
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
allow | array of string | 必填 | - | 对于符合匹配条件的请求,配置允许访问的consumer名 |
注意:
对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。
配置示例
1、对特定路由或域名开启
以下配置将对网关特定路由或域名开启 Key Auth 认证和鉴权,注意credential字段不能重复
全局配置
consumers:
- credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5name: consumer1
- credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35name: 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 状态码 | 出错信息 | 原因说明 |
---|---|---|
401 | No API key found in request | 请求未提供 API Key |
401 | Request denied by Key Auth check. Invalid API key | 不允许当前 API Key 访问 |
403 | Request denied by Basic Auth check. Unauthorized consumer | 请求的调用方无访问权限 |
请求屏蔽
功能说明
request-block
插件实现了基于 URL、请求头等特征屏蔽 HTTP 请求,可以用于防护部分站点资源不对外部暴露。
配置字段
名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
---|---|---|---|---|
block_urls | array of string | 选填,block_urls,block_headers,block_bodies 中至少必填一项 | - | 配置用于匹配需要屏蔽 URL 的字符串 |
block_headers | array of string | 选填,block_urls,block_headers,block_bodies 中至少必填一项 | - | 配置用于匹配需要屏蔽请求 Header 的字符串 |
block_bodies | array of string | 选填,block_urls,block_headers,block_bodies 中至少必填一项 | - | 配置用于匹配需要屏蔽请求 Body 的字符串 |
blocked_code | number | 选填 | 403 | 配置请求被屏蔽时返回的 HTTP 状态码 |
blocked_message | string | 选填 | - | 配置请求被屏蔽时返回的 HTTP 应答 Body |
case_sensitive | bool | 选填 | 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'
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
相关文章:

8.15日学习打卡---Spring Cloud Alibaba(三)
8.15日学习打卡 目录: 8.15日学习打卡为什么需要服务网关Higress是什么安装DockerCompose部署Higress创建网关微服务模块Higress路由配置Higress策略配置-跨域配置Higress解决如何允许跨域Higress策略配置之什么是HTTP认证Higress策略配置-Basic 认证什么是JWT认证J…...

2024下半年EI学术会议一览表
2024下半年将举办多个重要的EI学术会议,涵盖了从机器视觉、图像处理与影像技术到感知技术、绿色通信、计算机、大数据与人工智能等多个领域。 2024下半年EI学术会议一览表 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)将于2024…...

【海奇HC-RTOS平台E100-问题点】
海奇HC-RTOS平台E100-问题点 ■ btn 没有添加到group中 ,怎么实现的事件的■ 屏幕是1280*720, UI是1024*600,是否修改UI■ hc15xx-db-e100-v10-hcdemo.dtb 找不到■ 触摸屏驱动 能否给个实例■ 按键驱动■ __initcall(projector_auto_start)■ source insigt4.0 #if…...

性能测试之Mysql数据库调优
一、前言 性能调优前提:无监控不调优,对于mysql性能的监控前几天有文章提到过,有兴趣的朋友可以去看一下 二、Mysql性能指标及问题分析和定位 1、我们在监控图表中关注的性能指标大概有这么几个:CPU、内存、连接数、io读写时间…...

使用 RestHighLevelClient 进行 Elasticsearch 高亮查询及解析
在搜索引擎中,高亮显示查询关键字是一个提升用户体验的功能,它可以帮助用户更快地定位到相关信息。Elasticsearch 支持在搜索结果中对匹配的文本进行高亮显示。本文将介绍如何在 Java 应用程序中使用 Elasticsearch 的 RestHighLevelClient 执行高亮查询…...

Java基础入门15:算法、正则表达式、异常
算法(选择排序、冒泡排序、二分查找) 选择排序 每轮选择当前位置,开始找出后面的较小值与该位置交换。 选择排序的关键: 确定总共需要选择几轮:数组的长度-1。 控制每轮从以前位置为基准,与后面元素选择…...

SpringBoot响应式编程 WebFlux入门教程
🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法 🔥 微信:zsqtcyw 联系我领取学习资料 …...

LeetCode 383. 赎金信
题目 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1: 输入&…...

python绘制电路图
要在 Python 中实现电路图,你可以使用一些专门的库来创建和可视化电路图。一个常用的库是 schemdraw,它可以用来绘制电路图,并支持多种电气组件和符号。 下面是一个使用 schemdraw 库绘制简单电路图的示例: 安装 schemdraw 库&am…...

Vue3 Suspense 和 defineAsyncComponent 结合使用方法
Suspense:用于协调对组件树中嵌套的异步依赖的处理。 defineAsyncComponent:定义一个异步组件,它在运行时是懒加载的。参数可以是一个异步加载函数,或是对加载行为进行更具体定制的一个选项对象。 异步组件的好处:使…...

GitHub中Codespace怎么使用;LLM模拟初始化;MLP:全连接神经网络的并行执行
目录 PyUnit unittest是什么 unittest怎么使用 GitHub中Codespace怎么使用 测试常用功能 LLM模拟初始化 参数解释 类属性设置 总结 MLP:全连接神经网络的并行执行 假设 代码解释 注意事项 PyUnit unittest是什么 unittest是Python的内置单元测试框架,原名PyUn…...

【rh】rh项目部署
【fastadmin】 1、项目先clone到本地,其中web为h5前端使用(gitclone后,把web内容放进去再提交),其余为项目后端使用 2、安装本地环境,项目跑起来,步骤如下: 1)查春.git 和 composer,json 版本信…...

VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection
VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection Abstract 摘要部分,作者首先指出了3D点云中目标检测的重要性,在自动驾驶导航、家政机器人以及增强现实和虚拟现实等多个领域有重要的作用。然后,提到了现有方法的…...

结构开发笔记(三):solidworks软件(二):小试牛刀,绘制一个立方体
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141122350 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

LLM 量化算法AutoRound 0.3 发布及原理浅析
这里写自定义目录标题 AutoRound V0.3 特性原理浅析其他工作AutoRound 原理 AutoRound(https://github.com/intel/auto-round)在Llama3.1-8B-Instruct上效果明显优于AWQ/GPTQ等方法,在10个任务的平均准确率上我们以63.93%由于AWQ的63.15%和GP…...

汽车免拆诊断案例 | 2013款北京现代悦动车发动机偶尔无法起动
故障现象 一辆2013款北京现代悦动车,搭载G4FC发动机,累计行驶里程约为13.9万km。车主反映,发动机偶尔无法起动着机,断开点火开关,等待一会儿又可以起动着机。 故障诊断 接车后反复试车,当发动机无法起动着…...

React、AntD,封装动态表单
在React中使用Ant Design(简称AntD)来封装动态表单是一个常见的需求,特别是在需要灵活配置表单字段的场景下。以下是一个基本的步骤和示例代码,展示如何使用React和AntD来封装一个动态表单。 步骤 1: 安装必要的库 首先,确保你的项目中已经安装了react和antd。如果还没有…...

【Linux基础】Linux中的开发工具(3)--make/makefile和git的使用
目录 前言一,Linux项目自动化构建工具-make/makefile1. 背景2. 依赖关系和依赖方法3. 项目清理4. 使用方法和原理5. .PHONY的作用6. makefile中符号的使用 二,进度条的实现1. 理解回车换行2. 理解行缓冲区3. 版本14. 版本2 三,Linux上git的使…...

过滤了字母、数字、_、$的webshell命令执行技巧
目录 对于php5以上首先要解决的问题有 解决技巧 1.code长度小于35位 2.没有字母、数字、_ 、$ 3.怎么把文件放进服务器 4.怎么执行文件里面的内容 1.执行Linux命令 2.执行文件里面的shell命令 5.构造完整的code参数 6.我们还可以通过修改文件里面shell命令,…...

python-A+B again
[题目描述] 小理有一个非常简单的问题给你,给你两个整数 A 和 B,你的任务是计算 AB。输入格式: 输入共 2∗T1 行。 输入的第一行包含一个整数 T 表示测试实例的个数,然后 2∗T 行,分别表示 A 和 B 两个正整数。注意整数…...

C语言—函数递归
一、递归概念 递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。下面举一个例子: 上述就是⼀个简单的递归程序,只不过上⾯的递归只是为了演⽰递归的基本形式,不是为了解决问题,代码最终…...

结构开发笔记(四):solidworks软件(三):绘制36x36方块摄像头示意体
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/141187797 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...

【机器学习】Caltech-101的基本概念和使用方法以及Caltech-101和ImageNet的联系和区别
引言 Caltech-101数据集是一个广泛用于对象识别任务的数据库,它包含了大约9,000张图像,这些图像来自101个不同的对象类别。每个类别包含的图像数量大约在40到800张之间,大多数类别大约有50张图像。图像的分辨率大致为300200像素 文章目录 引言…...

mysql Ubuntu安装与远程连接配置
一、安装(Ubuntu22环境安装mysql8) 这里使用Xshell链接Ubuntu和mysql windows进行操作,特别提醒:安装之前建议对Ubuntu快照处理备份,避免安装中出错导致Ubuntu崩溃。 查看是否安装的有可以用指令:ps -ef|…...

c语言中比较特殊的输入格式
目录 一.%[ ] 格式说明符 1.基本用法 (1)读取字母字符: (2)读取数字字符: (3)读取所有字符直到遇到空格: (4)读取直到换行符: 2.使用范围和组合: 3.^ 取反操作 4.注意事项 (1). 字符范围的正确表示 (2). 避免字符集中的特殊字符冲突 (3).避免空字符集 (4). 输入长…...

远程命令行控制SSH
第一次接触SSH是ROS小车作为服务端,通过ubuntu电脑客户端访问。因为机器人接键盘和屏幕操作起来不方便,所以使用SSH进行连接,方便对小车的操作。 1.服务端安装 打开终端查看ssh是否安装 sudo service ssh status 如果未安装 sudo apt upd…...

钢铁百科:A572Gr60和SA572Gr60材质分析、A572Gr60和SA572Gr60简介
A572Gr60和SA572Gr60是两种常用的结构钢板,它们在材质、执行标准、化学成分、力学性能、交货状态、应用范围和常用规格方面有所不同。 材质: A572Gr60:属于美国材料与试验协会(ASTM)标准下的A572系列高性能结构钢&…...

一次sql请求,返回分页数据和总条数
日常搬砖,总少不了需要获取分页数据和总行数。 一直以来的实践是编码两次sql请求,分别拉分页数据和totalCount。 最近我在思考: 常规实践为什么不是 在一次sql请求中中执行多次sql查询或多次更新,显而易见的优势: ① 能…...

2.5 pyautogui 实现微信自动回复
第四节:实战微信自动回复 课程目标 学习如何通过pyautogui完成微信自动回复 课程内容 编码实现 import pyautogui as pg import time from pyautogui import ImageNotFoundException import pyperclip from cnocr import CnOcr import random ocr CnOcr() msg…...

观存储历史,论数据未来
数据存储 这几天我反复观看了腾讯云社区的《中国数据库前世今生》纪录片,每次的感受都大相径庭。以下是我在这段时间里对纪录片的两个不同感想,希望感兴趣的小伙伴们也能去观看一番。 一个是关于国产数据库的发展趋势的探讨:https://blog.c…...