一、前景
由于新配了https的域名,但不支持通过nginx将域名转为http,在界面有些地方的重定向会失效,显示“was loaded over HTTPS, but requested an insecure frame”报错,所以只能通过代码层面去解决。
项目是springboot+Thymeleaf,网上大概提了几种方法:
-
在页面上配上“<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">” -
controller里面的方法不要返回String,自己new一个RedirectView方法 -
设置redirectHttp10Compatible为false 这个参数默认是true,表示HTTP的状态码总是302,如果设置为false,则发送HTTP请求的时候变成303,对于HTTP1.1来说是正确的,但是对于HTTP1.0来说无法解析,即不兼容HTTP1.0。虽然对于很多HTTP1.1客户端来说,302和303这两个状态码并没有什么差别,但是在重定向的时候,对于有些客户端来说是需要303的状态码的,设置为false就是为了应对这些场景。
由于重定向地方较多,所以一个个改比较麻烦,就采用方法3,然后方法3网上说的那些方法好像都没有涉及到有Thymeleaf 的情况,在配置文件上配置viewResovler,指向InternalResourceViewResolver,但其实并没有生效,下面就来具体分析看看为啥没生效。
二、视图解析器
所谓重定向,即从一个地址调到另一个地址,是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL,重定向是客户端行为。SpringMVC主要是通过DispatcherServlet来转发请求,然后视图解析器来解析、创建视图。
?1、视图解析器
打断点后进来到ContentNegotiatingViewResolver这个方法,可以看出这里有4个视图解析器,这里的顺序是根据order这个值来的,可以看出第一位是BeanNameViewResolver,之所以是在第一位是因为在创建的时候,设置了order。
来到BeanNameViewResolver的resolveViewName方法中发现,它是直接从上下文中直接获取视图的,如果有就返回,但这个时候其实还没有视图的,所以来到第二个视图解析器ThymeleafViewResolver。
2、ThymeleafViewResolver
我们知道SpringBoot有自动装配bean的功能,主要是通过AutoConfigurationImportSelector来实现的,里面会读取META-INF/spring.factories文件,根据引入的依赖去装配各种bean,ThymeleafViewResolver就是通过里面的ThymeleafAutoConfiguration来创建的。?
这里也设置了order,比上面的BeanNameViewResolver多了5,所以排在第二,另外两个视图解析器ViewResolverComposite和InternalResourceViewResolver都是取的LOWEST_PRECEDENCE = Integer.MAX_VALUE,所以排在ThymeleafViewResolver后面。所以网上说的那些通过配置InternalResourceViewResolver的redirectHttp10Compatible为false不一定能生效,要看是否有其他视图解析器的顺序在其上面。?
此外,@ConditionalOnMissingBean(name = "thymeleafViewResolver")表示根据条件装配,所以当你知道了视图解析器的加载顺序,可能想把InternalResourceViewResolver换成ThymeleafViewResolver,但其实这时候会创建多一个ThymeleafViewResolver出来的,即这个时候会有两个ThymeleafViewResolver。如果你没有指定order,那么新创建的这个会排在原来的后面,只有设置了比原来的ThymeleafViewResolver小的order,才会加载自己配的这个。但由于这个是自己新建的,所以还需要配置引擎ISpringTemplateEngine和其他一些信息,比较麻烦。
三、SpringMVC重定向原理
就像前景里面的方法2,主要是创建RedirectView这个对象去实现的,无法就是根据不同的视图解析器,在不同的地方去创建而已。这里主要说的是ThymeleafViewResolver创建的过程。
创建RedirectView的时候,有个参数是指定http10Compatible,这个这里传的就是ThymeleafViewResolver的redirectHttp10Compatible属性,所以下面就要配置这个属性。?
public RedirectView(String url, boolean contextRelative, boolean http10Compatible) { ? super(url); ?
this.contextRelative = contextRelative; ?
this.http10Compatible = http10Compatible; ?
setExposePathVariables(false);
}
四、解决方法
基于上面的说明,我的解决方法是在启动类中获取到原来的ThymeleafViewResolver,然后设置一下那个属性。
ThymeleafViewResolver thymeleafViewResolver = (ThymeleafViewResolver) ? ? ?SpringContextUtil.getBean("thymeleafViewResolver");thymeleafViewResolver.setRedirectHttp10Compatible(false);
网络相关的可以看看这两个:
HTTP1.0和HTTP2.0的区别,以及HTTP和HTTPS的区别
计算机网络之HTTP、HTTPS、HTTP2
|