当前位置:网站首页>API Gateway/API 网关(四) - Kong的使用 - 集成Jwt和熔断插件
API Gateway/API 网关(四) - Kong的使用 - 集成Jwt和熔断插件
2022-04-23 14:11:00 【anron】
一、前言
使用Kong中的JWT插件需要先在Kong的Consumers中创建一个Consumer,然后在该Consumer的Credentials中设置JWT的key和secret。
假定在3个项目组中共用一个单点登录模块的这么一个场景,使用Kong网关来对JWT Token进行拦截。
- A项目组负责单点登录
/api/user 提供登录,登出的接口
- B项目组负责APP1
/api/app1 应用1
/api/common/app1 不需要登录的查询页面
- C项目组负责APP2
/api/app2 应用2
/api/common/app2 不需要登录的查询页面
Kong网关不对/api/user,/api/common进行JWT Token拦截,只对/api/app1,/api/app2进行JWT Token拦截
用户登录时调用/api/user/login接口验证用户名和密码,验证通过后系统将userid和mobile写入到JWT Token中,并以该Token为KEY放入redis中。
用户端登录后把JWT Token放入HTTP Header中,请求/api/app1或者/api/app2的应用接口,如果JWT Token无效或过期,在Kong网关就被拦截了,不会调用到后端的/api/app1或是/api/app2的应用接口。
app1或是app2接收到请求后,先读取出HTTP Header中的Authorization值(即:Bearer + 1个空格+Token),然后读取本项目中的redis,如果没找到数据就调用A项目组的远程接口(各个项目组有自己的DB,不可以互相访问其他项目的DB,只能通过远程接口来进行访问),出于安全性考虑,B和C项目组没有密钥,无法对Token进行解析,只有A项目组才能从Token中解析出UserID和Mobile。
Kong网关中没有找到这样的功能:自动解析Token中的UserID和Mobile,添加到Header后再调用后端的应用,不用后面再去解析。虽然Request Transformer插件可以remove/rename/replace/add/append对应的body/headers/querstring。
二、创建用户
2.1 添加Consumer
点击Consumers中的Create Consumer按钮,然后输入username,username=AllUsers,或者随便取个名称,只创建一个即可。
所有用户共用一个Consumer,即有优点也有缺点。
优点:不需要同步Kong中的Consumer和自己数据库的用户数据
缺点:限流等插件的使用只能按IP,不能按Consumer限制了。
2.2 创建Key和Secret
Credentials->JWT->Create JWT ,algorithm=HS256,其他默认空即可
三、添加JWT插件
设置claims to verify = exp,否则过期的token都可以请求,nbf可以不用设置
exp: 定义jwt的过期时间
nbf: 定义jwt的生效时间
设置了exp后,如果token过期了会提示"token expired"。
四、Java工程
单点登录工程下的部分模块,主要是JWT Token的颁发
4.1 修改POM文件
在pom.xml文件中添加jwt
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.3.0</version>
</dependency>
4.2 JwtUtil类
JWT_KEY、JWT_SECRET要与Kong中的Customer里面的设置相同
package com.anron.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
/**
* @Author: Anron
* @Date: 2020/4/13 14:07
*/
public class JwtUtil {
private static final String JWT_KEY = "9vQeIbdszK6Pq6Lcf0y8khnQ6yr5779P";
private static final String JWT_SECRET = "sZuEfoA9Vkwm8mhkM6Nr97eDX2YGdSu5";
/**
* 7天过期
*/
public static final long JWT_EXPIRATION = (long) 7 * 24 * 60 * 60000;
/**
* 测试环境30分钟过期
*/
public static final long JWT_EXPIRATION_TEST = (long) 30 * 60000;
/**
* iat 签发日期 withIssuedAt
* nbf 生效时间 withNotBefore
* exp 过期时间 withExpiresAt
* sub 主题
* iss 签发人
* aud 接收方
*/
public static String createJwtToken(Integer userId, String userNameOrMobile, long ttlMillis) {
String token = null;
try {
token = JWT.create()
.withIssuer(JwtUtil.JWT_KEY)
.withIssuedAt(new Date())
.withNotBefore(new Date())
.withClaim("userid", userId)
.withClaim("username", userNameOrMobile)
.withClaim("sub", "anron company")
.withExpiresAt(new Date(System.currentTimeMillis() + ttlMillis))
.sign(Algorithm.HMAC256(JwtUtil.JWT_SECRET));
} catch (JWTCreationException e){
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
return token;
}
public static DecodedJWT decryptToken(final String token) {
DecodedJWT jwt = null;
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(JwtUtil.JWT_SECRET))
.withIssuer(JwtUtil.JWT_KEY)
.build();
jwt = verifier.verify(token);
} catch (TokenExpiredException e) {
e.printStackTrace();
} catch (JWTDecodeException e){
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
return jwt;
}
}
4.3 Test类
package com.anron;
import com.anron.util.JwtUtil;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class AnronApplicationTests {
@Test
void contextLoads() {
Integer userId = 1001;
String userName = "admin";
String token = JwtUtil.createJwtToken(userId, userName, JwtUtil.JWT_EXPIRATION);
System.out.println(token);
}
@Test
void test1() {
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhbnJvbiBjb21wYW55IiwibmJmIjoxNTkwMTI3MTY3LCJpc3MiOiI5dlFlSWJkc3pLNlBxNkxjZjB5OGtoblE2eXI1Nzc5UCIsImV4cCI6MTU5MDczMTk2NywiaWF0IjoxNTkwMTI3MTY3LCJ1c2VyaWQiOjEwMDEsInVzZXJuYW1lIjoiYWRtaW4ifQ.AeoDSUZRPsoQAUfkJUTZJuU5e-CI5SEmihrHlw39Cuc";
DecodedJWT jwt = JwtUtil.decryptToken(token);
if (jwt != null) {
System.out.println("userid = " + jwt.getClaim("userid").asInt());
System.out.println("username = " + jwt.getClaim("username").asString());
System.out.println("sub = " + jwt.getClaim("sub").asString());
System.out.println("签发时间 = " + jwt.getClaim("iat").asDate());
System.out.println("生效时间 = " + jwt.getClaim("nbf").asDate());
System.out.println("过期时间 = " + jwt.getClaim("exp").asDate());
}
}
}
五、熔断插件
在Kong中添加个Request Termination插件,配置用默认即可
版权声明
本文为[anron]所创,转载请带上原文链接,感谢
https://blog.csdn.net/anron/article/details/105736816
边栏推荐
- 星界边境文本自动翻译机使用说明
- mysql 5.1升级到5.69
- On the multi-level certificate based on OpenSSL, the issuance and management of multi-level Ca, and two-way authentication
- JS format time
- redis数据库讲解(三)redis数据类型
- json date时间日期格式化
- 统信UOS卸载php7.2.24,安装php7.4.27 ;卸载再安装为PHP 7.2.34
- STD:: map and STD:: vector memory free
- gif转为静态图片处理
- Wechat applet rotation map swiper
猜你喜欢
利用json-server在本地创建服务器请求
使用Executors类快速创建线程池
Win10 comes with groove music, which can't play cue and ape files. It's a curvilinear way to save the country. It creates its own aimpack plug-in package, and aimp installs DSP plug-in
A table splitting implementation scheme of MySQL and InnoDB, MyISAM and MRG_ Introduction to MyISAM and other engine application scenarios
线程组ThreadGroup使用介绍+自定义线程工厂类实现ThreadFactory接口
squid代理
进入新公司,运维工程师从下面这几项了解系统的部署
win10自带Groove音乐不能播放CUE和APE文件的一种曲线救国办法,自己创建aimppack插件包,AIMP安装DSP插件
统信UOS卸载php7.2.24,安装php7.4.27 ;卸载再安装为PHP 7.2.34
RecyclerView高级使用(一)-侧滑删除的简单实现
随机推荐
js 抛物线运动方法封装
FBS (fman build system) packaging
PySide2
Request module
JS key value judgment
Gartner预测云迁移规模大幅增长;云迁移的优势是什么?
On the problem of cliff growth of loss function in the process of training
source insight via samba
Preview CSV file
使用开源调研工具Prophet是一种什么体验?
js 格式化时间
编译Openssl
Visio画拓扑图随记
Recyclerview advanced use (I) - simple implementation of sideslip deletion
正则表达式
JS format time
云容灾是什么意思?云容灾和传统容灾的区别?
Mysql的安装过程(已经安装成功的步骤说明)
線程組ThreadGroup使用介紹+自定義線程工廠類實現ThreadFactory接口
man man随记和crontab的@reboot用法