如何解决从GeoServer请求WMS/图片时的SameSite问题?
问题描述
我有一个HTML文件,通过<img>标签向GeoServer实例请求WMS图片。在Chrome浏览器打开该文件时,图片位置显示破碎图标;但把<img>的src链接直接粘贴到Chrome地址栏,却能正常显示GeoServer返回的图片。本地GeoServer实例(版本2.17.0)和AcuGIS托管的云端实例都出现这个问题。
通过Chrome开发者工具排查,发现是SameSite Cookie问题:JSESSIONID Cookie未设置SameSite属性或属性无效,浏览器默认采用SameSite=Lax策略,导致跨站请求中无法发送该Cookie,进而请求失败。
相关代码
<html> <head> <title>Leaflet WMS working</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/> <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script> <style> html, body { height: 100%; margin: 0; } #map { height: 80%; width: 100vw; } #input { width:100vw; height:20%; background-color:beige; } </style> </head> <body> <div id='map'></div> <div id='input'> <img src="http://localhost:8080/geoserver/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&WIDTH=20&HEIGHT=20&LAYER=dj:dj_raptor"> </div> <script> var map = L.map('map').setView([40.1, -104.8], 11); L.control.scale().addTo(map); var lyrOSM = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'}) lyrOSM.addTo(map); </script> </body> </html>
浏览器报错信息
由于Cookie未设置SameSite属性或属性无效,默认采用SameSite=Lax策略,导致该Cookie无法在跨站请求中发送。此行为可防止用户数据意外泄露给第三方,避免跨站请求伪造。 解决此问题需更新Cookie属性: - 如果需要在跨站请求中发送Cookie,设置`SameSite=None`和`Secure`属性,允许第三方使用。 - 如果不需要在跨站请求中发送Cookie,设置`SameSite=Strict`或`SameSite=Lax`属性。 涉及的Cookie: 名称 域名 & 路径 JSESSIONID localhost/geoserver 涉及的请求: png&WIDTH=20&HEIGHT=20&LAYER=dj:dj_raptor
解决方案
针对GeoServer 2.17.0版本,可通过以下方式设置Cookie的SameSite属性:
1. 修改Tomcat配置(本地部署GeoServer)
GeoServer默认运行在Tomcat容器中,修改Tomcat的配置文件:
- 打开Tomcat安装目录下的
conf/context.xml,在<Context>标签内添加:
<CookieProcessor sameSiteCookies="None" />
- 若使用HTTPS环境,需配合启用
Secure属性,确保Tomcat已配置HTTPS证书。
2. 配置GeoServer Web应用参数(无法修改Tomcat全局配置时)
在GeoServer的WEB-INF/web.xml中添加过滤器,自定义Cookie属性:
<filter> <filter-name>SameSiteCookieFilter</filter-name> <filter-class>org.apache.catalina.filters.CookieFilter</filter-class> <init-param> <param-name>sameSiteCookies</param-name> <param-value>None</param-value> </init-param> </filter> <filter-mapping> <filter-name>SameSiteCookieFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
注意:该方式要求Tomcat版本在9.0.21及以上,否则不支持CookieFilter的sameSiteCookies参数。
3. 云端托管GeoServer实例(如AcuGIS)
联系托管服务商,请求为GeoServer实例配置Cookie的SameSite=None属性,若使用HTTPS需同时启用Secure。也可查看服务商控制面板,确认是否有自定义Cookie属性的配置入口。
测试临时方案(仅用于调试,生产环境禁用)
如果在HTTP环境下测试,SameSite=None必须配合Secure但HTTP无法满足,可临时关闭Chrome的SameSite检查:在地址栏输入chrome://flags/#same-site-by-default-cookies,将选项设置为Disabled后重启浏览器。
内容的提问来源于stack exchange,提问作者bobbynaira

