微服务之网关安全基于Zuul并实现网关限流

2024-09-07 21:38

本文主要是介绍微服务之网关安全基于Zuul并实现网关限流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

微服务网关安全

微服务架构下的问题

处理安全和业务逻辑耦合,增加了复杂性和变更成本

随着业务节点增加,认证服务器压力增大

多个微服务同时暴露,增加了外部访问的复杂性

通过网关处理流程

1、请求令牌。2、转发请求。3、返回令牌。4、转发令牌各客户端应用。5、携带令牌发送请求。6、校验令牌。7、返回校验结果信息。8、访问微服务。

实例

引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- https://mvnrepository.com/artifact/com.marcosbarbero.cloud/spring-cloud-zuul-ratelimit --><dependency><groupId>com.marcosbarbero.cloud</groupId><artifactId>spring-cloud-zuul-ratelimit</artifactId><version>2.3.0.RELEASE</version></dependency>
</dependencies>
增加配置文件application.yml
zuul:routes:token:url: http://localhost:8085order:url: http://localhost:9080#敏感头,有三个敏感头,cookie,set-cookie,Authorizationsensitive-headers:
增加验证token过滤器
/*** 验证token*/
@Component
@Slf4j
public class OAuthFilter extends ZuulFilter {@Autowiredprivate RestTemplate restTemplate;/*** 提供四种过滤类型,pre-请求前,post-请求之后,error-出错之后,route-控制路由* @return*/public String filterType() {return "pre";}/*** 过滤器执行顺序* @return*/public int filterOrder() {return 1;}/*** 过滤器是否起作用,true,启用过滤器* @return*/public boolean shouldFilter() {return true;}/*** 要写的业务逻辑* @return* @throws ZuulException*/public Object run() throws ZuulException {log.info("oauth start");RequestContext requestContext=RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//请求开头是不是以token开头的,发往认证服务器的请求不用验证if(StringUtils.startsWith(request.getRequestURI(),"/token")){return null;}String requestHeader=request.getHeader("Authorization");if(StringUtils.isBlank(requestHeader)){return null;}if(!StringUtils.startsWithIgnoreCase(requestHeader,"bearer ")){return null;}try{TokenInfo tokenInfo=getTokenInfo(requestHeader);request.setAttribute("tokenInfo",tokenInfo);}catch(Exception e){log.info("get token info fail:",e);}return null;}private TokenInfo getTokenInfo(String requestHeader) {String token=StringUtils.substringAfter(requestHeader,"bearer ");String oauthServiceUrl="http://localhost:8085/oauth/check_token";HttpHeaders httpHeaders=new HttpHeaders();httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);httpHeaders.setBasicAuth("gateway","123456");//只能用这个map,用hashmap什么的,报错MultiValueMap<String,String> params=new LinkedMultiValueMap<String, String>();params.put("token", Collections.singletonList(token));HttpEntity<MultiValueMap<String,String>> entity=new HttpEntity<MultiValueMap<String, String>>(params,httpHeaders);ResponseEntity<TokenInfo> response=restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);log.info("token info:{}",response.getBody().toString());return response.getBody();}
}

创建自定义token响应,通过check_token接口拿到的token信息

@Data
public class TokenInfo {/*** token 是不是可用的*/private boolean active;/*** token是发往哪个客户端应用*/private String client_id;/*** 这个令牌的具有的权限*/private String[] scope;/*** 这个令牌发给哪个用户*/private String user_name;/*** 这个令牌哪些客户端ID可以访问*/private String[] aud;/*** 这个令牌的过期时间*/private Date exp;/*** 这个令牌所对应的用户的访问权限*/private String[] authorities;}

增加授权过滤器,在验证token过滤器之后执行,故filterOrder设置比验证token过滤器要大

/*** 授权过滤器*/
@Component
@Slf4j
public class AuthorizationFilter extends ZuulFilter {public String filterType() {return "pre";}public int filterOrder() {return 3;}public boolean shouldFilter() {return true;}public Object run() throws ZuulException {log.info("authorization start");RequestContext requestContext=RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();/*** 权限判断,是否需要认证*/if(isNeedAuth(request)){TokenInfo tokenInfo = (TokenInfo) request.getAttribute("tokenInfo");if(tokenInfo!=null&&tokenInfo.isActive()){if(!hasPermission(tokenInfo,request)){log.info("audit log update fail 403");handleError(403,requestContext);}requestContext.addZuulRequestHeader("username",tokenInfo.getUser_name());}else{if(!StringUtils.startsWith(request.getRequestURI(),"/token")){log.info("audit log update fail 401");handleError(401,requestContext);return null;}}}else{}return null;}/*** 模拟获取权限请求,50%的概率报403* @param tokenInfo* @param request* @return*/private boolean hasPermission(TokenInfo tokenInfo, HttpServletRequest request) {
//        return RandomUtils.nextInt()%2==0;return true;}private void handleError(int i, RequestContext requestContext) {requestContext.getResponse().setContentType("application/json");requestContext.setResponseStatusCode(i);requestContext.setResponseBody("{\"message\":\"auth fail\"}");requestContext.setSendZuulResponse(false);}private boolean isNeedAuth(HttpServletRequest request) {return true;}
}
zuul限流配置

pom文件增加

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.marcosbarbero.cloud/spring-cloud-zuul-ratelimit -->
<dependency><groupId>com.marcosbarbero.cloud</groupId><artifactId>spring-cloud-zuul-ratelimit</artifactId><version>2.3.0.RELEASE</version>
</dependency>

yml配置文件增加限流配置

zuul:routes:token:url: http://localhost:8085order:url: http://localhost:9080#敏感头,有三个敏感头,cookie,set-cookie,Authorizationsensitive-headers:ratelimit:enabled: true #限流是否起作用repository: jpa #存储位置default-policy-list: #默认策略- limit: 2quota: 1refresh-interval: 3type:- url- httpmethodpolicy-list: #针对于上面配置具体的服务限流规则token:- limit: 2quota: 1refresh-interval: 3type:- url- httpmethod
测试

在这里插入图片描述

注:3秒之内连续发送请求,报429错误,超过3秒,返回200

这篇关于微服务之网关安全基于Zuul并实现网关限流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146229

相关文章

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

python实现svg图片转换为png和gif

《python实现svg图片转换为png和gif》这篇文章主要为大家详细介绍了python如何实现将svg图片格式转换为png和gif,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录python实现svg图片转换为png和gifpython实现图片格式之间的相互转换延展:基于Py

Python利用ElementTree实现快速解析XML文件

《Python利用ElementTree实现快速解析XML文件》ElementTree是Python标准库的一部分,而且是Python标准库中用于解析和操作XML数据的模块,下面小编就来和大家详细讲讲... 目录一、XML文件解析到底有多重要二、ElementTree快速入门1. 加载XML的两种方式2.

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

C# foreach 循环中获取索引的实现方式

《C#foreach循环中获取索引的实现方式》:本文主要介绍C#foreach循环中获取索引的实现方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、手动维护索引变量二、LINQ Select + 元组解构三、扩展方法封装索引四、使用 for 循环替代

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将