简体   繁体   English

使用Spring Security配置应用程序以接受HTTP请求并发送HTTPS响应

[英]Configure Application using Spring Security to accept HTTP requests and send HTTPS response

I am new to the Spring Framework, and I have searched through every possible SO link related to this topic but could find any proper solution. 我是Spring框架的新手,我已经搜索了与该主题相关的所有可能的SO链接,但可以找到任何合适的解决方案。 I have an application running on JBoss Wildfly. 我有一个在JBoss Wildfly上运行的应用程序。 It sits on an AWS EC2 instance, which sits behind an Elastic Load Balancer(ELB). 它位于AWS EC2实例上,该实例位于Elastic Load Balancer(ELB)的后面。 The ELB has SSL configured in it so that it only accepts HTTPS requests from clients, my application server however communicates with the ELB only through HTTP. ELB中配置了SSL,因此它仅接受来自客户端的HTTPS请求,但是我的应用程序服务器仅通过HTTP与ELB通信。 My application uses both Spring MVC and Spring Security for front-end/security management. 我的应用程序同时使用Spring MVC和Spring Security进行前端/安全管理。 My security-context.xml file is as follows: 我的security-context.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

<context:property-placeholder location="/WEB-INF/config.properties" />
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.etech.security">          </context:component-scan>
<security:authentication-manager>
    <security:authentication-provider>
        <security:user-service>
            <security:user name="xxx@xxxx.com"
                authorities="admin" password="xxxxxxxx" />
        </security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:http use-expressions="true">
    <security:intercept-url pattern="/" access="isAuthenticated()" />
    <security:intercept-url pattern="/dashboard"
        access="isAuthenticated()" />
    <security:intercept-url pattern="/resources/**" access="permitAll" />
    <security:intercept-url pattern="/login" access="permitAll" />
    <security:intercept-url pattern="/**" access="denyAll" />
    <security:form-login login-page="/login"
        authentication-success-handler-ref="asyncAuthenticationSuccessHandler"
        authentication-failure-handler-ref="asyncAuthenticationFailureHandler" />
    <security:logout logout-url="/logout" logout-success-url="/" />

</security:http>
<bean id="asyncAuthenticationSuccessHandler"
    class="com.etech.security.AsyncAuthenticationSuccessHandler">
<constructor-arg ref="supportMailPassword"></constructor-arg>
</bean>

The problem with this setup is, once authenticated the application returns a HTTP link to the client, which the client cannot access as the ELB only allows HTTPS urls. 此设置的问题是,一旦通过身份验证,应用程序将向客户端返回HTTP链接,客户端无法访问该链接,因为ELB仅允许HTTPS url。 This is shown below: 如下所示:

Client --HTTPS---> ELB ---HTTP--> AppServer/Application 客户端--HTTPS ---> ELB --- HTTP-> AppServer / Application

Client <--HTTP-- ELB <---HTTP--- AppServer/Application 客户端<-HTTP-- ELB <-HTTP --- AppServer / Application

But it should actually do this, 但实际上应该这样做

Client --HTTPS---> ELB ---HTTP--> AppServer/Application 客户端--HTTPS ---> ELB --- HTTP-> AppServer / Application

Client <--HTTPS-- ELB <---HTTPS--- AppServer/Application 客户端<-HTTPS-- ELB <-HTTPS --- AppServer / Application

What is the right approach to this, do I need to use any kind of Filter that would bind to the Response after authentication/processing, where I can change the response url to HTTPS? 什么是正确的方法,我是否需要使用在身份验证/处理后可以绑定到Response的任何类型的Filter,可以在其中将响应URL更改为HTTPS?

After digging into the problem a little bit more I found out this was mainly due to the Spring Dispatcher Servlet detecting inbound connections as insecure, that is all connections were through HTTP, this would cause all outbound connections to be through HTTP as well. 在深入研究问题之后,我发现这主要是由于Spring Dispatcher Servlet将入站连接检测为不安全的,即所有连接都是通过HTTP进行的,这也会导致所有出站连接也都通过HTTP。

Spring would detect this through the following method call: HttpServletRequest.isSecure(), this will always return false as the connection from ELB to Application Server is through HTTP and not HTTPS. Spring将通过以下方法调用检测到这一点:HttpServletRequest.isSecure(),由于从ELB到Application Server的连接是通过HTTP而不是HTTPS进行的,因此它将始终返回false。

There is a nice blog post describing this exact same problem, and posting a simple solution that I used myself. 有一篇不错的博客文章描述了这个完全相同的问题,并发布了一个我自己使用的简单解决方案。

The solution is to use a filter that would be placed at the top of the filter chain. 解决方案是使用将放置在过滤器链顶部的过滤器。 It would intercept all incoming request, replace the inbound HttpServletRequest with a custom HttpServletRequest, that will have the isSecure() method returning true. 它将拦截所有传入的请求,用自定义HttpServletRequest替换入站HttpServletRequest,这将使isSecure()方法返回true。 Spring dispatcher Servlet would then detect this and send HTTPS responses back to the client. 然后,Spring调度程序Servlet将检测到此情况并将HTTPS响应发送回客户端。

The steps are simple: 步骤很简单:

  1. Create a custom HttpServletRequestWrapper 创建一个自定义HttpServletRequestWrapper

     public class CustomWrapper extends HttpServletRequestWrapper { public CustomWrapper(HttpServletRequest request) { super(request); } public boolean isSecure() { return true; } public String getScheme() { return "https"; } } 
  2. Create a Filter that would user this wrapper 创建一个将使用此包装器的过滤器

     public class CustomFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { CustomWrapper wrapper = new CustomWrapper((HttpServletRequest) request); chain.doFilter(wrapper, response); } @Override public void init(FilterConfig arg0) throws ServletException { } 

    } }

  3. In web.xml add this filter before any other filter, including Spring Security Filter chain. 在web.xml中,将此过滤器添加到任何其他过滤器之前,包括Spring Security过滤器链。

暂无
暂无

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

相关问题 如何使用Spring Security Java配置将HTTP请求重定向到HTTPS? - How to redirect HTTP requests to HTTPS using Spring Security Java configuration? 如何使用Spring Security仅接受https流量并拒绝所有http流量? - How to accept only https traffic and deny all http traffic using Spring Security? 我想要接受 https 请求并将此请求发送到 http 上的其他应用程序并将此 http 响应发送回 https req 的 Spring Boot 应用程序 - I want spring boot application which accepts https request and send this request to other app on http and send this http response back to https req Spring Security和Angular 6 HTTPS请求 - Spring Security And Angular 6 HTTPS requests Spring Boot,如何使用application.proerties配置spring安全性 - Spring Boot, how to configure spring security using application.proerties Spring Security SAML,在使用 SAMLContextProviderLB 设置为 HTTPs 方案时重定向到 HTTP 而不是 HTTPS - Spring Security SAML, Redirects going to HTTP instead of HTTPS when using SAMLContextProviderLB set to HTTPs scheme 如何在Web应用程序中配置spring security? - How to configure spring security in a web application? 如何为单页应用程序配置Spring Security? - How to configure Spring Security for a single page application? 使用捕获的数据包从服务器向应用程序发送http响应 - Send http response to application from server using captured packets Spring Security:如何更改响应的 HTTP 状态? - Spring Security: how to change HTTP Status for response?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM