宁安网站建设,网络营销策划书的范文,表情包制作网站,河源市新闻最新消息问题描述#xff1a; 在最近的一个项目中#xff0c;有一个存在较久#xff0c;并且只在内部城域网可访问的一个使用Shiro框架进行安全管理的Java应用#xff0c;该应用部署在Tomcat服务器上。起初#xff0c;应用程序可以通过HTTP协议访问#xff0c;一切运行都没…问题描述 在最近的一个项目中有一个存在较久并且只在内部城域网可访问的一个使用Shiro框架进行安全管理的Java应用该应用部署在Tomcat服务器上。起初应用程序可以通过HTTP协议访问一切运行都没问题。然而当我们决定切换到HTTPS协议以增强客户端通常是网络浏览器与服务器之间的安全通信时问题随之产生主要问题现象如下 例如登录页面的URL是https://***/login任何尝试访问受Shiro保护的页面的操作都应该重定向用户到这个登录页面。但问题在于即使在启用HTTPS协议并尝试使用HTTPS协议访问这些受保护的页面系统仍然不断地将浏览器重定向到http://***/login这就启用HTTPS协议后遇到的主要问题。 我们部署架构中一个值得注意的方面是网络前端有一个物理负载均衡器负责处理SSL认证。通过HTTPS协议发出的请求首先到达这个负载均衡器然后再通过HTTP协议转发到Tomcat Web服务器结构如下图其中响应中的Location Header在用户使用https访问页面时预期应该返回https://***/login但实际却返回了http://***/login
问题解决 想了下问题应该就是因为负载卸载了证书实际到达Tomcat的请求协议是HTTP的导致Shiro识别到的请求协议是HTTP所以跳转地址便使用了HTTP而不是实际的HTTPS。 先是查了下资料定位到Shiro会根据一个Header名字为X-Forwarded-Proto值是https或http)来获取通过反向代理进来的请求的实际使用协议(因为大多数SSL证书处理都是在反向代理上卸载掉, 倒是到达应用时的请求都是HTTP)。同时Tomcat的server.xml需要增加配置来识别这个Header用来初始化HttpServletRequest内的属性, 实际影响的就是request.getScheme()这个方法的返回值。
具体修改步骤
第一步修改反向代理配置增加X-Forwarded-Proto Header
如果是硬负载比如A10或者F5例如针对https协议需要配置如下 一般针对https和http协议会建立两个模板分别处理443端口和80端口的请求。 如果是Nginx是下面这样配置 第二步修改Tomcat配置
在Tomcat的server.xml配置文件中EngineHost标签下增加如下配置其中remoteIpHeader这个是用于获取外部实际ip的一般一并加上了。protocolHeaderHttpsValue也可以不加因为https是默认值加上这个一般一般情况下Java代码通过request.getScheme()方法就可以获取用户请求实际使用的协议了Shiro也就可以根据实际协议去拼装登录页面URL了。
Valve classNameorg.apache.catalina.valves.RemoteIpValveremoteIpHeaderx-forwarded-forprotocolHeaderx-forwarded-protoprotocolHeaderHttpsValuehttps /
第三步: Tomcat额外配置可选
我这里配置了以上两步以后,后端request.getScheme()方法仍然获取的是http因为知道scheme这个值是RemoteIpValve这个类处理的就看了下代码发现server.xml中关于RemoteIpValve还有一个配置项叫internalProxies是一个关于ip的正则表达式代码中有一个if条件只有当反向代理的ip可以通过正则匹配成功才会处理x-forwarded-*的header。并且Tomcat 7中正则缺少172段ip更新版本的Tomcat可以匹配10.x.x.x, 192.168.x.x, 169.254.x.x, 127.x.x.x, 和172.16.x.x 到 172.31.x.x。 所以当反向代理服务器或者设备的ip不在以上范围的时候需要主动在RemoteIpValve配置中增加internalProxies的配置如下这里是Tomcat 7所以需要手动处理172段ip
Valve classNameorg.apache.catalina.valves.RemoteIpValveinternalProxies172\.31\.1\.22remoteIpHeaderx-forwarded-forprotocolHeaderx-forwarded-protoprotocolHeaderHttpsValuehttps /总结
成功修改以上配置后Shiro可以正常通过request.getScheme()获取用户请求使用的实际协议也就解决了用户通过https访问页面但是跳转登录页面时协议变成了http的问题。