带有 spring-boot-starter-web 的 Spring Cloud Gateway
Posted
技术标签:
【中文标题】带有 spring-boot-starter-web 的 Spring Cloud Gateway【英文标题】:Spring Cloud Gateway with spring-boot-starter-web 【发布时间】:2021-04-02 09:39:17 【问题描述】:我正在使用 Spring Cloud Gateway 为 Spring Boot 微服务创建网关。 Gateway 还负责使用 Spring Security 进行 JWT 授权。
public class JwtAuthorizationFilter extends BasicAuthenticationFilter
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException
String header = request.getHeader(JwtProperties.HEADER_STRING);
if (header == null || !header.startsWith(JwtProperties.TOKEN_PREFIX))
chain.doFilter(request, response);
return;
Authentication authentication = getUsernamePasswordAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
private Authentication getUsernamePasswordAuthentication(HttpServletRequest request)
String token = request.getHeader(JwtProperties.HEADER_STRING).replace(JwtProperties.TOKEN_PREFIX, "");
DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC512(JwtProperties.SECRET.getBytes())).build().verify(token);
String username = decodedJWT.getSubject();
if (username != null)
UserPrincipal principal = (UserPrincipal) userPrincipalService.loadUserByUsername(username);
Authentication auth = new UsernamePasswordAuthenticationToken(username, null, principal.getAuthorities());
return auth;
return null;
这个过滤器在configure方法中注册如下:
@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter
...
@Override
protected void configure(HttpSecurity http) throws Exception
http
.cors()
.and()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtAuthorizationFilter(authenticationManager(), userPrincipalService))
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
...
.anyRequest().authenticated();
...
如您所见,Spring Security 使用了属于 spring-boot-starter-web 的 HttpServletRequest、HttpServletResponse、FilterChain 接口。但这是主要问题,因为它与 Spring Cloud Gateway 不兼容。
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.
有什么方法可以避免这个错误,或者有什么不同的解决方案在网关上实现 jwt 授权过滤器? 谢谢!
【问题讨论】:
【参考方案1】:Documentation of spring cloud gateway 中明确指出该产品运行在 Netty 之上并且需要 webflux,因此它与 spring MVC 不兼容。
您使用的过滤器 (JwtAuthorizationFilter
) 属于非反应性世界,因此您可能应该使用 spring security 重写它以用于 Web Flux 构建块。
免责声明,我不是 spring web Flux/spring-security 专家,但请考虑检查 This application - 它展示了如何使用响应式 spring security 版本定义 JWT 安全应用程序。
因此,最重要的是,您应该选择是想要响应式应用程序还是传统应用程序,并使用相关技术,但您不能真正混合使用它们。
【讨论】:
以上是关于带有 spring-boot-starter-web 的 Spring Cloud Gateway的主要内容,如果未能解决你的问题,请参考以下文章
手写自定义springboot-starter,感受框架的魅力和原理
SpringBoot 源码解析 ----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)