简体   繁体   English

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

[英]Spring security change redirect URL to use HTTPS instead of HTTP

I'm working with a Spring microservice protected with Spring Security SSO login (Using Cloudfoundry UAA). 我正在使用受Spring Security SSO登录保护的Spring微服务(使用Cloudfoundry UAA)。

Microservice when deployed on Cloud is accessible via HTTPS URL. 部署在云上的微服务可通过HTTPS URL访问。 Since HTTPS URL is of the ELB (Load balancer/web server), actual request to microservice from ELB comes on HTTP . 由于HTTPS URL是ELB(负载均衡器/ Web服务器),因此对ELB的微服务的实际请求来自HTTP So Spring when redirecting the user to login page produces HTTP URL instead of HTTPS URL in 302 Location header. 因此Spring将用户重定向到登录页面时会在302 Location标题中生成HTTP URL而不是HTTPS URL。

Following is the flow 以下是流程

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)

Following is what I have tried 以下是我的尝试

x-forwarded-proto 的x转发-原

Since load balancer is also not populating x-forwarded-proto correctly to HTTPS , instead it gives me HTTP , I can't use Spring's support for it. 由于负载均衡器也没有正确地将x-forwarded-proto填充到HTTPS ,而是它给了我HTTP ,我不能使用Spring的支持。

Require channel HTTPS 需要渠道HTTPS

It also doesn't work, as it results in infinite redirections from Spring as Spring never receives an HTTPS request from ELB , despite correctly having produced HTTPS redirect URL. 它也不起作用,因为它导致Spring无限重定向,因为Spring从未收到来自ELB的HTTPS请求,尽管正确生成了HTTPS重定向URL。

Interceptor/Filter 拦截器/过滤器

Use a ServletFilter to check response header Location and if present replace http:// with https:// . 使用ServletFilter检查响应头Location ,如果存在,则用https://替换http:// https://

Frankly last option is my final option as I do not control the ELB configuration. 坦率地说,最后一个选项是我的最终选项,因为我不控制ELB配置。

Now issue is that I'm unable to intercept the response after spring redirects to /login URL which in turn should redirect to SSO URL. 现在的问题是,我无法在Spring重定向到/login URL后拦截响应,而后者又应该重定向到SSO URL。

I have tried various combinations of Interceptors (postHandle, afterCompletion), using Spring security to inject it at various locations in the filter chain and finally setting the filter order to lowest. 我尝试过拦截器的各种组合(postHandle,afterCompletion),使用Spring安全性将其注入过滤器链中的不同位置,最后将过滤器顺序设置为最低。 None of these intercept unauthenticated request after redirection. 这些都不会在重定向后拦截未经身份验证的请求。

@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);

    }
}

How do I correctly intercept the /login redirection by Spring Security in a filter/interceptor and update Location header to include correct protocol? 如何在过滤器/拦截器中正确拦截Spring Security的/login重定向并更新Location头以包含正确的协议?

Any hint is appreciated. 任何提示都表示赞赏。

If you want to update Location header info you can try to use an HttpResponseInterceptor. 如果要更新Location头信息,可以尝试使用HttpResponseInterceptor。

This is an example of use from google HttpResponseInterceptor: https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/http/HttpResponseInterceptor 这是使用Google HttpResponseInterceptor的一个示例: https//developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/ HTTP / HttpResponseInterceptor

Other option is from Apache: https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/class-use/HttpResponseInterceptor.html 其他选项来自Apache: https//hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/class-use/HttpResponseInterceptor.html

SpringFramework provides the HandlerInterceptor. SpringFramework提供了HandlerInterceptor。 This will intercept all http request, but can be used to constantly check for authentication and authorization. 这将拦截所有http请求,但可用于不断检查身份验证和授权。 You will have to provide implementations for 3 methods (if you don't use them just implement an empty method). 您必须提供3种方法的实现(如果您不使用它们,只需实现一个空方法)。 You can then put your code in the preHandle method. 然后,您可以将代码放在preHandle方法中。

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 {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM