【问题标题】:How to enforce HTTPS for static content with Tomcat + Spring Security如何使用 Tomcat + Spring Security 对静态内容实施 HTTPS
【发布时间】:2015-08-06 19:05:01
【问题描述】:

我有一个运行在 Tomcat 8 服务器上的 Spring 4.1.1、Spring security 3.2.5、JSF 2.2.3 Web 应用程序。

我需要所有内容(包括所有静态内容)都只能通过 HTTPS 访问。

我设法为动态内容执行此操作,但静态内容仍可通过 HTTP 直接访问,例如使用 URL http://localhost:8080/static/images/image.png。我还需要将其重定向到 HTTPS。

server.xml

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

<Connector port="8443" SSLEnabled="true"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="true" disableUploadTimeout="true"
    acceptCount="100" debug="0" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLSv1"
    keystoreFile="C:/Java/jdk1.8.0_40/bin/keystore.jks"
    keystorePass="xxx" />

web.xml

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<security-constraint>
  <web-resource-collection>
      <web-resource-name>Automatic HTTPS Redirect</web-resource-name>
      <url-pattern>/*</url-pattern>
  </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<security-constraint>
  <web-resource-collection>
      <web-resource-name>Restricted Methods</web-resource-name>
      <url-pattern>/*</url-pattern>
      <http-method>PUT</http-method>
      <http-method>DELETE</http-method>
      <http-method>TRACE</http-method>
      <http-method>OPTIONS</http-method>
  </web-resource-collection>
  <auth-constraint />
</security-constraint>

spring_security.xml(精简版)

<?xml version="1.0" encoding="UTF-8"?>

<beans >
    <!-- Configure Spring Security -->
    <security:authentication-manager alias="authenticationManager">
      <security:authentication-provider user-service-ref="userDetailsService">
        <security:password-encoder ref="passwordEncoderBean">
            <security:salt-source ref="saltSource"/>
        </security:password-encoder>
      </security:authentication-provider>
    </security:authentication-manager>  

    <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" >
        <property name="userPropertyToUse" value="salt"/>
    </bean>

    <bean id="passwordEncoderBean" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
        <constructor-arg value="256" />
    </bean>

    <bean id="userDetailsService" class="com.pippo.security.UserDetailsImpl"/>

    <bean id="authenticationProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">  
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="authenticationFailureHandler" ref="failureHandler" />
        <property name="authenticationSuccessHandler" ref="successHandler" />
        <property name="filterProcessesUrl" value="/spring/loginProcess"/>
    </bean>  

    <bean id="successHandler" class="com.pippo.security.pippoAuthenticationSuccessHandler" >
        <property name="defaultTargetUrl" value="/spring/flows/client_main_flow" />
        <property name="roleManager" ref="roleManager" />
        <property name="geoIPManager" ref="geoIPManager" />
        <constructor-arg>
            <map value-type="java.lang.String" key-type="java.lang.String">
                <entry key="ROLE_ADMIN" value="/spring/flows/admin_main_flow"/>
                <entry key="ROLE_ANON" value="/spring/flows/public"/>
                <entry key="DENIED" value="/spring/flows/access_denied"/>
            </map>
        </constructor-arg>
    </bean>
    <bean id="failureHandler" class="com.pippo.security.CustomAuthenticationFailureHandler" >
        <property name="defaultFailureUrl" value="/pippo" />
    </bean>

    <bean id="authenticationEntryPoint"  class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/spring/flows/public"/>
    </bean>

    <security:http entry-point-ref="authenticationEntryPoint" pattern="/spring/**">
        <security:anonymous />
        <security:http-basic />
        <security:custom-filter position="FORM_LOGIN_FILTER" ref="authenticationProcessingFilter" />
        <security:logout logout-url="/spring/logout" success-handler-ref="logoutController"/>
        <security:intercept-url pattern="/spring/login" access="ROLE_ANON,ROLE_USER,ROLE_ADMIN" />
        <security:intercept-url pattern="/spring/logoutSuccess" access="ROLE_ANON,ROLE_USER" />
        <security:intercept-url pattern="/spring/intro" access="ROLE_ANON,ROLE_USER"  />
        <security:intercept-url pattern="/spring/flows/admin_main_flow/**" access="ROLE_ADMIN" />
    </security:http>

    <security:http security="none" pattern="/javax.faces.resource/**" />
    <security:http security="none" pattern="/ajax/**" />
    <security:http security="none" pattern="/static/**" />
    <security:http security="none" pattern="/resources/**" />
    <security:http security="none" pattern="/spring/flows/public/**" />

    <bean id="logoutController" class="com.pippo.security.LogoutHandlerImpl"/>

  <bean id="eventDispatcher" class="com.pippo.listener.EventDispatcher"/>

</beans>

请注意,如果我加载包含对静态内容(如 CSS 或 JavaScript 文件或图像)的安全引用的任何页面,则所有静态内容都会通过 HTTPS 正确检索。问题在于静态内容的直接 URL,如上面的 (http://localhost:8080/static/images/image.png) 应该重定向到 HTTPS 但不是。

我也尝试添加拦截 URL 来代替 security none,但它也不起作用:

<security:http pattern="/static/**" entry-point-ref="authenticationEntryPoint" use-expressions="true">
    <security:intercept-url pattern="/static/**" requires-channel="https" access="permitAll"/>
</security:http>

我猜是Tomcat配置不对,但我想不通。

【问题讨论】:

    标签: spring tomcat https


    【解决方案1】:

    &lt;security:http security="none" pattern="url-pattern" /&gt; 表示 Spring Security 不会拦截任何遵循模式匹配 url-pattern 的请求。因此,您的静态资源 URL 不在 Spring Security 框架的范围内。

    为了实现所需的行为,配置应更改为:

    <security:intercept-url access="permitAll" pattern="url-pattern" requires-channel="https"/>
    

    此配置表示应允许所有用户访问与模式 url-pattern 匹配的 URL,并且应对这些 URL 强制执行 HTTPS。

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 2017-03-08
      • 2018-12-25
      • 2019-03-04
      • 2011-02-01
      • 1970-01-01
      • 2019-02-19
      • 2021-06-19
      相关资源
      最近更新 更多