SpringBoot之Zuul服务

server/2024/9/25 4:29:17/

概述

Spring Cloud Netflix zuul组件是微服务架构中的网关组件,其核心功能是路由和过滤,目前公司业务就是基于Zuul搭建的网关服务,本文主要内容:Zuul的执行流程、Zuul过滤实现、Zuul安全配置

Zuul服务

Zuul执行流程

  • 接收请求
    • 客户端发送请求到Zuul服务器(前置经过Nginx反向代理)
  • Pre-filters
    • 请求首先通过Pre类型的过滤器,这些过滤器可以进行安全检查、身份验证、日志记录、选择路由等操作。
  • 路由转发Routing
    • 如果Pre-filter通过请求将被路由到具体的微服务实例上。Zuul 可以根据配置的路由规则将请求转发到不同的后端服务。
  • 服务调用
    • Zuul通过Fegin进行客户端负载均衡,选择一个服务实例进行调用
  • Post-filters
    • 服务处理完成后,响应会返回并经过 Post 类型的过滤器,这些过滤器可以修改返回的响应头、收集统计信息等。最终Zuul将响应发送回客户端
  • Error-filters
    • 如果在任何阶段发生错误,请求将被转发到 Error 类型的过滤器,进行错误处理后经过Post-filters,最终Zuul将响应发送回客户端

Zuul过滤器

pre-filter

前置过滤器在请求被路由到源服务器之前执行,通常继承ZuulFilter抽象类。实际项目中我们使用前置过滤器对于400到500的状态错误码进行过滤,进而对于从cas认证服务中获取token的特定请求进行错误日志的记录

package test.gateway.filter;import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import test.common.util.R;
import com.google.gson.Gson;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;/*** @Description: 捕获400到500错误码,否则不执行该过滤器*/
public class ErrorStatusCodeZuulFilter extends ZuulFilter {protected static String GET_TOKEN_URI =  "/cas/getToken";@Overridepublic String filterType() {return "post";}@Overridepublic int filterOrder() {return -1; // Needs to run before SendResponseFilter which has filterOrder == 0}@Overridepublic boolean shouldFilter() {    		int statusCode = Integer.parseInt(RequestContext.getCurrentContext().get("responseStatusCode").toString());return statusCode >= 400 && statusCode <= 500;}@Overridepublic Object run() {RequestContext ctx = RequestContext.getCurrentContext();int statusCode = Integer.parseInt( ctx.get("responseStatusCode").toString());	String uri = ctx.get("requestURI").toString();if (uri != null && uri.equals(GET_TOKEN_URI)) { //获取token请求失败R<String>  res = new R<>();		res.setCode(statusCode);res.setData(null);res.setMsg("Account or password error");ctx.setResponseBody(new Gson().toJson(res));return null;}try {throw new Exception();} catch (Throwable t) {	    		throw new ZuulRuntimeException(new ZuulException(t, statusCode, t.getMessage()));}}
}
routing-filter

处理将请求发送到源服务器的逻辑

post-filter

后置过滤器在请求被路由后执行,可以对响应进行修改或添加额外的HTTP等。

error-filter

当请求处理过程中发生错误时,这些过滤器会被调用,同时最终也会调用后置post类型过滤器返回 

扩展-OncePerRequestFilter

OncePerRequestFilter是Spring Framework中的一个接口,它属于Servlet过滤器(Filter)的范畴,但不是Zuul中定义的特定过滤器类型。在Spring MVC中,OncePerRequestFilter确保每个请求只被处理一次。它通过同步代码块来保证,即使在支持异步处理的 Spring MVC 应用程序中,请求也不会被重复处理。项目中我们通过自定义过滤器(继承OncePerRequestFilter)处理访问公共接口且未携带token的请求,该过滤器也属于前置的过滤器,因为它通常用于在请求进入其他阶段之前执行某些操作。

Zuul安全配置

自定义WebSecurityConfig

在Spring Security的上下文中,WebSecurityConfig类通常用于配置Spring Security的安全策略。此类继承自WebSecurityConfigurerAdapter,WebSecurityConfig可以用来定义Zuul网关的安全设置,通过提供了一种自定义安全配置的方法实现,实际项目中我们对zuul进行的http请求相关安全配置

package test.zuul.config;
import .../*** @Description: Zuul http configuration*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // 定义Zuul网关的安全设置private final static Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);@Autowiredprivate FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;@Autowiredprivate FindByIndexNameSessionRepository<? extends Session> sessionRepository;@Autowiredprivate RedisOperationsSessionRepository redisOperationsSessionRepository; @Autowiredprivate AuthenticationServiceFeign authenticationService;@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable(); //禁用csrfhttp.headers().frameOptions().disable();ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry =http.antMatcher("/**") // 允许所有请求.authorizeRequests();filterIgnorePropertiesConfig.getUrls().forEach(url -> registry.antMatchers(url).permitAll());registry.anyRequest().authenticated();http.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login/idpbg"))	        .and().logout().logoutUrl("/logout").addLogoutHandler(new LogoutHandler() { //登出后处理逻辑@Overridepublic void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {					if(authentication != null) {String indexName = authentication.getName();// 查询用户的 Session 信息      Map<String, ? extends Session> userSessions = sessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, indexName);// 删除当前用户相关sessionList<String> sessionIds = new ArrayList<>(userSessions.keySet());for (String session : sessionIds) {redisOperationsSessionRepository.deleteById(session);}//删除系统当前在线用户信息...}Cookie cookie = new Cookie();//重置cookie...response.addCookie(cookie);}}).logoutSuccessHandler(logoutSuccessHandler()).oauth2Login().and().oauth2Client();	}private LogoutSuccessHandler logoutSuccessHandler() { //登出成功后处理逻辑return new LogoutSuccessHandler() {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {if(authentication != null) {if(authentication.getDetails() instanceof OAuth2AuthenticationDetails) {// 刪除JWT......}}new SecurityContextLogoutHandler().logout(request, null, null);try {response.sendRedirect("/"); //重定向到登录页面}} catch (IOException e) {e.printStackTrace();}}};}
}


http://www.ppmy.cn/server/34655.html

相关文章

详解Go语言Map

Map的声明 使用make()函数定义Map map_name : make(map[KeyType]valueType,initialCapacity)KeyType是键的类型&#xff0c;ValueType是值的类型&#xff0c;initialCapacity是可选参数&#xff0c;用于指定map的初始容量。 使用map关键字定义Map m : map[string]int {&quo…

iOS - Undefined symbols: 解决方法

Undefined symbols: 是让人苦恼的报错&#xff0c;如何知道是 哪个 symbols 不对呢&#xff1f; 今天探索到下面的方法&#xff1a; 1、点击导航上方 最右侧的按钮&#xff0c;查看历史报错 2、选中报错信息&#xff0c;右键选择 Expand All Transcripts 在出现的详细信息面…

03.配置监控一台服务器主机

配置监控一台服务器主机 安装zabbix-agent rpm -ivh https://mirror.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.11-1.el7.x86_64.rpm配置zabbix-agent,配置的IP地址是zabbix-server的地址&#xff0c;因为要监控这台主机 vim /etc/zabbix/zab…

spring-cloud-starter-alibaba-nacos-discovery如何从nacos上获得已经注册的服务地址

在Spring Cloud中&#xff0c;可以使用Spring Cloud Alibaba Nacos Discovery来从Nacos服务器获取所有微服务的地址。你需要在你的微服务中添加以下依赖&#xff1a; <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-star…

使用 SSH 连接 GitHub Action 服务器

前言 Github Actions 是 GitHub 推出的持续集成 (Continuous integration&#xff0c;简称 CI) 服务它提供了整套虚拟服务器环境&#xff0c;基于它可以进行构建、测试、打包、部署项目&#xff0c;如果你的项目是开源项目&#xff0c;可以不限时使用服务器硬件规格&#xff1…

Docker 入门与实践:从零开始构建容器化应用环境

Docker 一、docker常用命令docker ps 格式化输出Linux设置命令别名 二、数据卷相关命令挂载到默认目录&#xff08;/var/lib/docker&#xff09;挂载到本地目录 三、自定义镜像Dockerfile构建镜像的命令 四、网络自定义网络 五、DockerCompose相关命令 一、docker常用命令 dock…

扩展学习|本体研究进展

文献来源&#xff1a; 王向前,张宝隆,李慧宗.本体研究综述[J].情报杂志,2016,35(06):163-170. 一、本体的定义 本体概念被引入人工智能、知识工程等领域后被赋予了新的含义。然而不同的专家学者对本体的理解不同,所给出的定义也有所差异。 人工智能领域的学者Neches(1991)等人对…

可编程 IP 新星 Story Protocol 何以引领链上文艺复兴浪潮?

当前&#xff0c;随着 Web3 行业发展进入全新阶段&#xff0c;与生成式人工智能&#xff08;AIGC&#xff09;技术融合正在创造潜力新星项目。也是目前的互联网生态下&#xff0c;任何普通民众都有权利创作高质量的音乐、艺术、散文和视频内容&#xff0c;带来了用户生成内容&a…