微服务之网关安全基于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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter