有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring安全更改重定向URL以使用HTTPS而不是HTTP

我正在使用一个受Spring安全SSO登录保护的Spring微服务(使用Cloudfoundry UAA)

部署在云上的微服务可以通过HTTPSURL访问。由于HTTPS URL是ELB(负载平衡器/web服务器)的URL,所以来自ELB的对微服务的实际请求来自HTTP。因此,Spring在将用户重定向到登录页面时,会在302 Location头中生成HTTP URL而不是HTTPS URL

以下是流程

Browser
    ->(https://mymicroservice.com) Unauthenticated request (Load balancer)
        ->(http://internal_lan_ip:someport) Microservice
            -> 302 Location http://mymicroservice.com/login
                -> Browser http://mymicroservice.com/login (failed)

In short it goes from HTTPS -> HTTP -> 302 HTTP (failed as ELB doesn't serve on HTTP)

以下是我尝试过的

x-forwarded-proto

由于负载平衡器也没有将x-forwarded-proto正确地填充到HTTPS,相反,它给了我HTTP,所以我不能使用Spring对它的支持

需要频道HTTPS

它也不起作用,因为它会导致来自Spring的无限重定向,因为Spring从未收到来自ELB的HTTPS请求,尽管正确地生成了HTTPS重定向URL

拦截器/过滤器

使用ServletFilter检查响应头Location,如果存在,则将http://替换为https://

坦白地说,最后一个选项是我的最终选项,因为我不控制ELB配置

现在的问题是,在spring重定向到/loginURL之后,我无法截获响应,而该URL又应该重定向到SSO URL

我尝试了各种拦截器组合(postHandle、afterCompletion),使用SpringSecurity在过滤器链中的不同位置注入拦截器,最后将过滤器顺序设置为最低。在重定向后,所有这些都不会拦截未经验证的请求

@Component
@Order(Ordered.LOWEST_PRECEDENCE)
class RedirectUrlProtocolUpdaterFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String locationHeader = response.getHeader("Location");
        System.out.println("############ inside interceptor");

        for(String name: response.getHeaderNames()) {
            System.out.println(name + " : " + response.getHeader(name));
        }

        if(locationHeader != null && locationHeader.startsWith("http://")) {
            System.out.println("###################### setting location header");

            locationHeader = locationHeader.replaceAll("http://", "https://");
            response.setHeader("Location", locationHeader);
        }

        filterChain.doFilter(request, response);

    }
}

如何在筛选器/侦听器中正确拦截Spring Security的/login重定向,并更新位置头以包含正确的协议

任何暗示都将不胜感激


共 (2) 个答案

  1. # 1 楼答案

    SpringFramework提供了HandlerInterceptor。这将拦截所有http请求,但可用于不断检查身份验证和授权。您必须为3个方法提供实现(如果不使用它们,只需实现一个空方法)。然后可以将代码放入预处理方法中

    public class AuthenticationInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        }
    }