配置https后403的问题
维护一老项目,配置https后,post请求始终响应403。
已知请求过程为:https=>nginx=>http=>tomcat
查看nginx日志,请求正常接收并代理,403由上层应用响应而来
查看tomcat日志,正常接收到请求并响应,403由业务应用响应而来
查看应用日志,只看到一个shiro的Found Cookie的输出,目标方法并无任何日志打印,说明请求已经进入应用,被应用中某个地方直接响应403了
比较客户端http请求头和https请求头,发现https请求头中多一个Origin,在nginx中,使用proxy_set_header Origin http://xxxx.xxx.com
强制将客户端的https请求设置为http请求,业务正常响应。
由此可知,此问题为跨域问题:
当我们的浏览器发出跨站请求时,行为正确的服务器会校验当前请求是不是来自被允许的站点。服务器就是通过 Origin 字段的值来进行的判断。
当服务器的配置出错时,比如配置成了 https://baidu.com/,则可能造成一些难以理解的问题。
比如有的浏览器(IE)能够请求成功,而有的浏览器却请求失败(Chrome)。这不是因为前一个浏览器行为正确,而是因为前一个浏览器发出请求时没有带上 Origin 而后一个浏览器带上了正确的 Origin。而在服务器端,因为没有 Origin Header,所以认为这不是一次 CORS 请求,所以没有进行 CORS 校验。这也反过来要求服务端强制请求带上 Origin Header,才能进一步保证服务器的安全性。
检查项目中的跨域配置,在web.xml中看到如下配置:
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
org.apache.catalina.filters.CorsFilter用于跨域设置,其可设置参数为:
于是在cros配置中加上allow-origins即可:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
</filter>
应用日志中能看到shiro输出,是因为filter配置中,shiro在前,cros在后,请求在cros处被拦截并响应回403!