spring boot实现超轻量级网关(反向代理转发)
Posted shenjun980326
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot实现超轻量级网关(反向代理转发)相关的知识,希望对你有一定的参考价值。
spring boot实现超轻量级网关(反向代理、转发)
原文连接 https://www.cnblogs.com/xiaoqi/p/spring-boot-route.html
在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景。可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定。
如何进行请求转发呢? 熟悉网络请求的同学应该很清楚,请求无非就是请求方式、HTTP header,以及请求body,我们将这些信息取出来,透传给转发的url即可。
举例:
/router/** 转发到 businessServer/**
获取转发目的地址:
private String createRedirectUrl(HttpServletRequest request, String routeUrl, String prefix)
String queryString = request.getQueryString();
return routeUrl + request.getRequestURI().replace(prefix, "") +
(queryString != null ? "?" + queryString : "");
解析请求头和内容
然后从request中提取出header、body等内容,构造一个RequestEntity,后续可以用RestTemplate来请求。
private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException
String method = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(method);
MultiValueMap<String, String> headers = parseRequestHeader(request);
byte[] body = parseRequestBody(request);
return new RequestEntity<>(body, headers, httpMethod, new URI(url));
private byte[] parseRequestBody(HttpServletRequest request) throws IOException
InputStream inputStream = request.getInputStream();
return StreamUtils.copyToByteArray(inputStream);
private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request)
HttpHeaders headers = new HttpHeaders();
List<String> headerNames = Collections.list(request.getHeaderNames());
for (String headerName : headerNames)
List<String> headerValues = Collections.list(request.getHeaders(headerName));
for (String headerValue : headerValues)
headers.add(headerName, headerValue);
return headers;
透明转发
最后用RestTemplate来实现请求:
private ResponseEntity<String> route(RequestEntity requestEntity)
RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(requestEntity, String.class);
全部代码
以下是轻量级转发全部代码:
import com.jyw.router.miniapp.service.IRouterService;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
/**
* @author 黑子桑
* @ClassName IRouterServiceImpl
* @Description TODO
* @Date 2023/4/20 13:32
**/
@Service
public class RouterServiceImpl implements IRouterService
@Override
public ResponseEntity<String> redirect(HttpServletRequest request, HttpServletResponse response,String routeUrl, String prefix)
try
// build up the redirect URL
String redirectUrl = createRedirectUrl(request,routeUrl, prefix);
RequestEntity requestEntity = createRequestEntity(request, redirectUrl);
return route(requestEntity);
catch (Exception e)
return new ResponseEntity("REDIRECT ERROR", HttpStatus.INTERNAL_SERVER_ERROR);
private String createRedirectUrl(HttpServletRequest request, String routeUrl, String prefix)
String queryString = request.getQueryString();
return routeUrl + request.getRequestURI().replace(prefix, "") +
(queryString != null ? "?" + queryString : "");
private RequestEntity createRequestEntity(HttpServletRequest request, String url) throws URISyntaxException, IOException
String method = request.getMethod();
HttpMethod httpMethod = HttpMethod.resolve(method);
MultiValueMap<String, String> headers = parseRequestHeader(request);
byte[] body = parseRequestBody(request);
return new RequestEntity<>(body, headers, httpMethod, new URI(url));
private ResponseEntity<String> route(RequestEntity requestEntity)
RestTemplate restTemplate = new RestTemplate();
return restTemplate.exchange(requestEntity, String.class);
private byte[] parseRequestBody(HttpServletRequest request) throws IOException
InputStream inputStream = request.getInputStream();
return StreamUtils.copyToByteArray(inputStream);
private MultiValueMap<String, String> parseRequestHeader(HttpServletRequest request)
HttpHeaders headers = new HttpHeaders();
List<String> headerNames = Collections.list(request.getHeaderNames());
for (String headerName : headerNames)
List<String> headerValues = Collections.list(request.getHeaders(headerName));
for (String headerValue : headerValues)
headers.add(headerName, headerValue);
return headers;
本文来自博客园,作者:黑子桑,转载请注明原文链接:https://www.cnblogs.com/shenjun980326/p/spring-boot-route.html
在反向代理后面使用 OAuth2 的 Spring Boot
【中文标题】在反向代理后面使用 OAuth2 的 Spring Boot【英文标题】:Spring Boot with OAuth2 behind reverse proxy 【发布时间】:2019-05-01 09:23:38 【问题描述】:我是 Spring Security 的新手,并尝试使用在主机名:8080 下运行的 OAuth2 开发带有 Google 登录的 Spring Boot 应用程序。此应用位于 Apache 反向代理服务器 https://url.com 后面。
Spring Boot 2.1.0 版
Spring Security 5.1.1 版
build.gradle:
dependencies
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.security:spring-security-oauth2-client")
implementation("org.springframework.security:spring-security-oauth2-jose")
application.yml:
oauth2:
client:
registration:
google:
clientId: <clientId>
clientSecret: <clientSecret>
scope: profile, email, openid
server:
use-forward-headers: true
servlet:
session:
cookie:
http-only: false
Spring 安全配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http
.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login();
-
我请求https://url.com
被重定向到https://accounts.google.com/signin/oauth/
经过身份验证后被重定向回
https://url.com/login/oauth2/code/google?state=state&code=code&scope=openid+email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.me&authuser=0&session_state=session_state&prompt=none 超时错误:
[invalid_token_response] 尝试 检索 OAuth 2.0 访问令牌响应:POST 上的 I/O 错误 请求“https://www.googleapis.com/oauth2/v4/token”:连接 超时(连接超时);嵌套异常是 java.net.ConnectException:连接超时(连接超时)
此错误是由代理服务器设置或启动应用程序引起的吗?感谢您的帮助。
【问题讨论】:
显示你的反向代理配置。 【参考方案1】:解决了。我必须设置 JVM 参数:
https.proxyHost=[host]
https.proxyPort=[port]
http.proxyHost=[host]
http.proxyPort=[port]
【讨论】:
您的应用程序是否在主机上运行,主机有一些防火墙规则来禁止直接访问 Internet?为什么设置 JVM 代理参数有帮助?以上是关于spring boot实现超轻量级网关(反向代理转发)的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot - Apache 反向代理背后的 Spring 安全性
NGINX 反向代理背后的 Spring Boot API REST
在反向代理后面使用 OAuth2 的 Spring Boot