如何将 Spring Security 与负载均衡器一起使用?
Posted
技术标签:
【中文标题】如何将 Spring Security 与负载均衡器一起使用?【英文标题】:How to use Spring Security with load balancer? 【发布时间】:2022-01-01 00:27:21 【问题描述】:我是 loadBalancing 的新手,所以我需要帮助,这就是我所做的: 我将 2 个服务构建为 2 个应用程序(A、B)我在它们两个上都使用了 Spring Security (它们都是 restfull api,它们有 ymleaf 和完整的前端页面), 然后我做了另一个应用程序作为弹簧云负载平衡器。 当我发送请求时,它会从负载平衡器应用程序转到 2 个服务之一,但问题是当我未通过身份验证时,响应将为空,它不会像我使用普通 A 应用程序时一样将我带到默认登录页面直接,当我转到不需要经过身份验证才能访问它的页面时,它会在没有我的 css/js 样式的情况下返回
这是我的 A 应用控制器(它返回的不是 json 视图)
package com.hariri_stocks.controllers;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.hariri_stocks.models.Estates;
import com.hariri_stocks.models.SoldEstates;
import com.hariri_stocks.models.Users;
import com.hariri_stocks.services.estatesService;
@Controller
public class LoginController
@Autowired
estatesService ES;
@GetMapping(value = "/")
public String login()
return "/signIn-up.html";
@GetMapping(value = "/dashboard")
public String dashboard(Model model ,@RequestParam(required = false) String add_result
,@RequestParam(required = false) String alert_err)
List<Estates> estates = ES.findAll();
model.addAttribute("estates",estates);
return "/dashboard";
@GetMapping(value = "/dashboard/unSold")
public String unselled_stocks(Model model)
List<Estates> estates = ES.findUnsold();
if(estates.size() > 0)
model.addAttribute("estates",estates);
else
model.addAttribute("error","there is no sold estates yet !!");
return "/dashboard";
@Value(value = "$server.port")
String port_num;
@GetMapping("/port")
public String hello()
return port_num;
这是我使用 @restcontroller 的负载平衡器控制器
package com.hariri_loadbalancer;
import reactor.core.publisher.Mono;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
@SpringBootApplication
@RestController
public class UserApplication
private final WebClient.Builder loadBalancedWebClientBuilder;
private final ReactorLoadBalancerExchangeFilterFunction lbFunction;
public UserApplication(WebClient.Builder webClientBuilder,
ReactorLoadBalancerExchangeFilterFunction lbFunction)
this.loadBalancedWebClientBuilder = webClientBuilder;
this.lbFunction = lbFunction;
public static void main(String[] args)
SpringApplication.run(UserApplication.class, args);
@RequestMapping("/port")
public Mono<String> showMePort()
return loadBalancedWebClientBuilder.build().get().uri("http://hariri/port")
.retrieve().bodyToMono(String.class);
@RequestMapping("/")
public Mono<String> showMainPage()
return loadBalancedWebClientBuilder.build().get().uri("http://hariri/")
.retrieve().bodyToMono(String.class);
那我该怎么办?我觉得我在做的事情很愚蠢, 我是否应该将我所有的 Thymleaf 页面移动到负载均衡器,以便应用程序返回它想要返回的内容 @restController 然后负载均衡器使用 @controller 进入样式首页或者有一种方法,并且为了安全,我应该使用负载均衡器而不是 A、B 应用程序来实现弹簧安全吗 ………………………………………………………………………………………………………… 8080 是负载均衡器端口 9091 是一个应用程序端口 所以它接缝当A返回html页面时,html正在8080的负载均衡器机器上搜索css,而它们存在于9091的A应用程序中
【问题讨论】:
请使用详细的 curl 或邮递员对 LoginController 进行接受和拒绝的请求,并粘贴完整的响应(包括标题)。也通过负载均衡器做同样的事情。我相信你会注意到一些不同的东西。 【参考方案1】:bodyToMono 对正文进行解码,但您没有处理标题。 在 Spring Security 上,很可能会重定向到登录页面......所以如果你只关注身体,它就不会起作用。这可能也会以某种方式影响样式。
检查以下内容: How to extract response header & status code from Spring 5 WebClient ClientResponse
【讨论】:
对于样式,它在负载均衡应用程序上搜索它们,而它们在应用程序 A ... @muhammad 我认为这也可能是一个配置问题。无论如何,IMO 你不应该将你的样式表移动到 LB。那是混合的担忧。您可以将它们放置在一些类似 CDN 的具有非常长的 TTL 缓存中,因此它们是可访问的和高性能的。以上是关于如何将 Spring Security 与负载均衡器一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
负载均衡器后面带有 Spring Security 的 Spring Boot:将 HTTP 重定向到 HTTPS
Grails Spring Security 使用 https 重定向到登录页面
(031)Spring Boot之服务的注册与发现,使用zookeeper演示负载均衡
(031)Spring Boot之服务的注册与发现,使用zookeeper演示负载均衡