请求头重命名:原Header名称 __ajax、__sid、__remember,更改为 x-ajax, x-token,

x-remember(升级注意);新增
ajaxParamName、ajaxHeaderName、contentSecurityPolicy、sessionIdHeaderName、writeCookieParamName、rememberMeHeaderName
参数设置,使用方法详见 yml 注释
This commit is contained in:
thinkgem
2021-05-17 14:56:12 +08:00
parent c4bdc8d643
commit d3518144c9
4 changed files with 152 additions and 104 deletions

View File

@@ -8,7 +8,6 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.TreeMap;
@@ -25,7 +24,6 @@ import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.io.PropertiesUtils;
import com.jeesite.common.lang.ExceptionUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.mapper.XmlMapper;
@@ -40,13 +38,26 @@ public class ServletUtils {
public static final String EXT_PARAMS_PREFIX = "param_"; // 扩展参数前缀
// 定义静态文件后缀静态文件排除URI地址
private static String[] staticFiles;
private static String[] staticFileExcludeUri;
private static Boolean favorPathExtension;
private static Boolean favorParameter;
private static Boolean favorHeader;
private static Boolean jsonp;
private static final PropertiesUtils PROPS = PropertiesUtils.getInstance();
private static final String[] STATIC_FILE = StringUtils.split(PROPS.getProperty("web.staticFile"), ",");
private static final String[] STATIC_FILE_EXCLUDE_URI = StringUtils.split(PROPS.getProperty("web.staticFileExcludeUri"), ",");
// AJAX 请求参数和请求头名
public static final String AJAX_PARAM_NAME = PROPS.getProperty("web.ajaxParamName", "__ajax");
public static final String AJAX_HEADER_NAME = PROPS.getProperty("web.ajaxHeaderName", "x-ajax");
// MVC 偏好设置根据后缀、参数、Header 返回特定格式数据
public static final Boolean FAVOR_PATH_EXTENSION = PROPS.getPropertyToBoolean("web.view.favorPathExtension", "false");
public static final Boolean FAVOR_PARAMETER = PROPS.getPropertyToBoolean("web.view.favorParameter", "true");
public static final Boolean FAVOR_HEADER = PROPS.getPropertyToBoolean("web.view.favorHeader", "true");
// JSONP 支持(为兼用旧版保留,建议使用 CORS
public static final Boolean JSONP_ENABLED = PROPS.getPropertyToBoolean("web.jsonp.enabled", "false");
public static final String JSONP_CALLBACK = PROPS.getProperty("web.jsonp.callback", "__callback");
// 是否打印错误信息参数到视图页面(生产环境关闭)
private static final Boolean PRINT_ERROR_INFO = PROPS.getPropertyToBoolean("error.page.printErrorInfo", "true");
/**
* 获取当前请求对象
* web.xml: <listener><listener-class>
@@ -105,51 +116,28 @@ public class ServletUtils {
* @throws Exception
*/
public static boolean isStaticFile(String uri){
if (staticFiles == null){
PropertiesUtils pl = PropertiesUtils.getInstance();
try{
staticFiles = StringUtils.split(pl.getProperty("web.staticFile"), ",");
staticFileExcludeUri = StringUtils.split(pl.getProperty("web.staticFileExcludeUri"), ",");
}catch(NoSuchElementException nsee){
; // 什么也不做
}
if (staticFiles == null){
try {
throw new Exception("检测到“jeesite.yml”中没有配置“web.staticFile”属性。"
+ "配置示例:\n#静态文件后缀\nweb.staticFile=.css,.js,.png,.jpg,.gif,"
+ ".jpeg,.bmp,.ico,.swf,.psd,.htc,.crx,.xpi,.exe,.ipa,.apk");
} catch (Exception e) {
e.printStackTrace();
}
if (STATIC_FILE == null){
try {
throw new Exception("检测到“jeesite.yml”中没有配置“web.staticFile”属性。"
+ "配置示例:\n#静态文件后缀\nweb.staticFile=.css,.js,.png,.jpg,.gif,"
+ ".jpeg,.bmp,.ico,.swf,.psd,.htc,.crx,.xpi,.exe,.ipa,.apk");
} catch (Exception e) {
e.printStackTrace();
}
}
if (staticFileExcludeUri != null){
for (String s : staticFileExcludeUri){
if (STATIC_FILE_EXCLUDE_URI != null){
for (String s : STATIC_FILE_EXCLUDE_URI){
if (StringUtils.contains(uri, s)){
return false;
}
}
}
if (StringUtils.endsWithAny(uri, staticFiles)){
if (StringUtils.endsWithAny(uri, STATIC_FILE)){
return true;
}
return false;
}
/**
* 初始化一些个性化配置
* @author ThinkGem
*/
private static void initWebViewConfig() {
if (favorPathExtension == null || favorParameter == null || favorHeader == null || jsonp == null) {
PropertiesUtils props = PropertiesUtils.getInstance();
favorPathExtension = ObjectUtils.toBoolean(props.getProperty("web.view.favorPathExtension", "false"));
favorParameter = ObjectUtils.toBoolean(props.getProperty("web.view.favorParameter", "true"));
favorHeader = ObjectUtils.toBoolean(props.getProperty("web.view.favorHeader", "true"));
jsonp = ObjectUtils.toBoolean(props.getProperty("web.jsonp.enabled", "false"));
}
}
/**
* 是否是Ajax异步请求
* @param request
@@ -166,9 +154,7 @@ public class ServletUtils {
return true;
}
initWebViewConfig();
if (favorPathExtension) {
if (FAVOR_PATH_EXTENSION) {
String uri = request.getRequestURI();
if (StringUtils.endsWithIgnoreCase(uri, ".json")
|| StringUtils.endsWithIgnoreCase(uri, ".xml")){
@@ -176,15 +162,15 @@ public class ServletUtils {
}
}
if (favorParameter) {
String ajaxParameter = request.getParameter("__ajax");
if (FAVOR_PARAMETER) {
String ajaxParameter = request.getParameter(AJAX_PARAM_NAME);
if (StringUtils.inStringIgnoreCase(ajaxParameter, "json", "xml")){
return true;
}
}
if (favorHeader) {
String ajaxHeader = request.getHeader("__ajax");
if (FAVOR_HEADER) {
String ajaxHeader = request.getHeader(AJAX_HEADER_NAME);
if (StringUtils.inStringIgnoreCase(ajaxHeader, "json", "xml")){
return true;
}
@@ -234,8 +220,7 @@ public class ServletUtils {
String exMsg = ExceptionUtils.getExceptionMessage(ex);
if (StringUtils.isNotBlank(exMsg)){
resultMap.put("message", message + "" + exMsg);
}else if (ObjectUtils.toBoolean(PropertiesUtils.getInstance()
.getProperty("error.page.printErrorInfo", "true"))){
}else if (PRINT_ERROR_INFO){
resultMap.put("message", message + "" + ex.getMessage());
}
}else if (data instanceof Map){
@@ -248,9 +233,9 @@ public class ServletUtils {
HttpServletResponse response = getResponse();
HttpServletRequest request = getRequest();
if (request != null){
String uri = request.getRequestURI(); initWebViewConfig();
if ((favorPathExtension && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (favorParameter && StringUtils.equalsIgnoreCase(request.getParameter("__ajax"), "xml"))){
String uri = request.getRequestURI();
if ((FAVOR_PATH_EXTENSION && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (FAVOR_PARAMETER && StringUtils.equalsIgnoreCase(request.getParameter(AJAX_PARAM_NAME), "xml"))){
if (response != null){
response.setContentType(MediaType.APPLICATION_XML_VALUE);
}
@@ -260,8 +245,8 @@ public class ServletUtils {
return XmlMapper.toXml(resultMap);
}
}
if (jsonp) {
String functionName = request.getParameter("__callback");
if (JSONP_ENABLED) {
String functionName = request.getParameter(JSONP_CALLBACK);
if (StringUtils.isNotBlank(functionName)){
object = new JSONPObject(functionName, resultMap);
}
@@ -337,13 +322,13 @@ public class ServletUtils {
*/
public static String renderObject(HttpServletResponse response, Object object, Class<?> jsonView) {
HttpServletRequest request = getRequest();
String uri = request.getRequestURI(); initWebViewConfig();
if ((favorPathExtension && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (favorParameter && StringUtils.equalsIgnoreCase(request.getParameter("__ajax"), "xml"))){
String uri = request.getRequestURI();
if ((FAVOR_PATH_EXTENSION && StringUtils.endsWithIgnoreCase(uri, ".xml"))
|| (FAVOR_PARAMETER && StringUtils.equalsIgnoreCase(request.getParameter(AJAX_PARAM_NAME), "xml"))){
return renderString(response, XmlMapper.toXml(object));
}
if (jsonp) {
String functionName = request.getParameter("__callback");
if (JSONP_ENABLED) {
String functionName = request.getParameter(JSONP_CALLBACK);
if (StringUtils.isNotBlank(functionName)){
object = new JSONPObject(functionName, object);
}

View File

@@ -309,12 +309,12 @@ gen:
# 系统监控
state:
enabled: true
#======================================#
#========= Framework settings =========#
#======================================#
# Shiro 相关配置
# Shiro 相关
shiro:
#索引页路径
@@ -354,9 +354,9 @@ shiro:
# 指定获取客户端IP的Header名称防止IP伪造。指定为空则使用原生方法获取IP。
remoteAddrHeaderName: X-Forwarded-For
# 允许的请求方法设定,解决安全审计问题
allowRequestMethods: GET,POST,OPTIONS,PUT,DELETE
# 允许的请求方法设定,解决安全审计问题BPM设计器用到了PUT或DELETE方法
allowRequestMethods: GET, POST, OPTIONS, PUT, DELETE
# 是否允许账号多地登录如果设置为false同一个设备类型的其它地点登录的相同账号被踢下线
isAllowMultiAddrLogin: true
@@ -370,21 +370,22 @@ shiro:
# 是否允许嵌入到外部网站iframe中true不限制false不允许
isAllowExternalSiteIframe: true
# 是否允许跨域访问 CORS如果允许设置允许的域名。当设置'*'号全部域名时accessControlAllowCredentials应该设置为false。
# v4.2.3 开始支持多个域名和模糊匹配例如http://*.jeesite.com,http://*.jeesite.net
# accessControlAllowOrigin: http://demo.jeesite.com
# accessControlAllowOrigin: '*'
# 允许跨域访问时 CORS可以使用的方法和标头
# accessControlAllowMethods: GET, POST, OPTIONS
# accessControlAllowHeaders: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With
# 是否允许接收跨域的Cookie凭证数据 CORS当设置为true时accessControlAllowOrigin不能设置为'*'。
# accessControlAllowCredentials: false
# 设定允许获取的资源列表v4.2.3
#contentSecurityPolicy: "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; img-src 'self' 'unsafe-inline' 'unsafe-eval' data:"
# 是否允许跨域访问 CORS如果允许设置允许的域名。v4.2.3 开始支持多个域名和模糊匹配例如http://*.jeesite.com,http://*.jeesite.net
accessControlAllowOrigin: '*'
# 允许跨域访问时 CORS可以获取和返回的方法和请求头
#accessControlAllowMethods: GET, POST, OPTIONS
#accessControlAllowHeaders: content-type, x-requested-with, x-ajax, x-token, x-remember
#accessControlExposeHeaders: x-remember
# 是否允许接收跨域的Cookie凭证数据 CORS
#accessControlAllowCredentials: false
# 允许的网站来源地址,不设置为全部地址(避免一些跨站点请求伪造 CSRF、防盗链
# allowReferers: http://127.0.0.1,http://localhost
# allowReferers: ~
#allowReferers: http://127.0.0.1,http://localhost
# 是否在登录后生成新的Session默认false
isGenerateNewSessionAfterLogin: false
@@ -406,6 +407,8 @@ shiro:
# ${adminPath}/sys/corpAdmin/treeData = anon
# ${adminPath}/${spring.application.name}/swagger/** = anon
# ${adminPath}/** = user
# URI 权限过滤器定义(自定义添加参数时,请不要移除 ${adminPath}/** = user否则会导致权限异常
filterChainDefinitions: |
${adminPath}/** = user
@@ -460,8 +463,16 @@ session:
#sessionIdCookieHttpOnly: true
#sessionIdCookieSameSite: LAX
# 设置接收SessionId请求参数的名称
# 设置接收 SessionId 请求参数和请求头的名称
sessionIdParamName: __sid
sessionIdHeaderName: x-token
# 当直接通过 __sid 参数浏览器访问页面时,可将直接将 __sid 写入 Cookie 应用于后面的访问
# 访问地址举例http://host/js/a/index?__sid=123456&__cookie=true
writeCookieParamName: __cookie
# 记住我的请求参数和请求头的名称v4.2.3
rememberMeHeaderName: x-remember
# 系统缓存配置
j2cache:
@@ -513,6 +524,10 @@ mybatis:
# Web 相关
web:
# AJAX 接受参数名和请求头名v4.3.0
ajaxParamName: __ajax
ajaxHeaderName: x-ajax
# MVC 视图相关
view:
@@ -528,7 +543,7 @@ web:
favorPathExtension: false
# 使用 __ajax=json、__ajax=xml 后缀匹配返回视图数据
favorParameter: true
# 使用 __ajax=json、__ajax=xml 请求头匹配返回视图数据
# 使用 x-ajax=json、x-ajax=xml 请求头匹配返回视图数据
favorHeader: true
# MVC 拦截器
@@ -578,6 +593,7 @@ web:
# 默认不启用(为兼用旧版保留,建议使用 CORS
jsonp:
enabled: false
callback: __callback
# 核心模块的Web功能仅作为微服务时设为false
core:
@@ -600,7 +616,7 @@ file:
enabled: true
# 文件上传根路径设置路径中不允许包含“userfiles”在指定目录中系统会自动创建userfiles目录如果不设置默认为contextPath路径
# baseDir: D:/jeesite
#baseDir: D:/jeesite
# 上传文件的相对路径支持yyyy, MM, dd, HH, mm, ss, E
uploadPath: '{yyyy}{MM}/'
@@ -638,7 +654,7 @@ video:
# 视频格式转换 ffmpeg.exe 所放的路径
ffmpegFile: d:/tools/video/ffmpeg-4.9/bin/ffmpeg.exe
# ffmpegFile: d:/tools/video/libav-10.6-win64/bin/avconv.exe
#ffmpegFile: d:/tools/video/libav-10.6-win64/bin/avconv.exe
# 视频格式转换 mencoder.exe 所放的路径
mencoderFile: d:/tools/video/mencoder-4.9/mencoder.exe

View File

@@ -427,7 +427,7 @@ logging:
#========= Framework settings =========#
#======================================#
# Shiro 相关配置
# Shiro 相关
shiro:
# #索引页路径
@@ -468,8 +468,8 @@ shiro:
# # 指定获取客户端IP的Header名称防止IP伪造。指定为空则使用原生方法获取IP。
# remoteAddrHeaderName: X-Forwarded-For
#
# # 允许的请求方法设定,解决安全审计问题
# allowRequestMethods: GET,POST,OPTIONS,PUT,DELETE
# # 允许的请求方法设定,解决安全审计问题BPM设计器用到了PUT或DELETE方法
# allowRequestMethods: GET, POST, OPTIONS, PUT, DELETE
#
# # 是否允许账号多地登录如果设置为false同一个设备类型的其它地点登录的相同账号被踢下线
# isAllowMultiAddrLogin: true
@@ -483,21 +483,22 @@ shiro:
# # 是否允许嵌入到外部网站iframe中true不限制false不允许
# isAllowExternalSiteIframe: true
#
# # 是否允许跨域访问 CORS如果允许设置允许的域名。当设置'*'号全部域名时accessControlAllowCredentials应该设置为false。
# # v4.2.3 开始支持多个域名和模糊匹配例如http://*.jeesite.com,http://*.jeesite.net
## accessControlAllowOrigin: http://demo.jeesite.com
## accessControlAllowOrigin: '*'
#
# # 允许跨域访问时 CORS可以使用的方法和标头
## accessControlAllowMethods: GET, POST, OPTIONS
## accessControlAllowHeaders: Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With
#
# # 是否允许接收跨域的Cookie凭证数据 CORS当设置为true时accessControlAllowOrigin不能设置为'*'。
## accessControlAllowCredentials: false
# # 设定允许获取的资源列表v4.2.3
# #contentSecurityPolicy: "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; img-src 'self' 'unsafe-inline' 'unsafe-eval' data:"
#
# # 是否允许跨域访问 CORS如果允许设置允许的域名。v4.2.3 开始支持多个域名和模糊匹配例如http://*.jeesite.com,http://*.jeesite.net
# #accessControlAllowOrigin: '*'
#
# # 允许跨域访问时 CORS可以获取和返回的方法和请求头
# #accessControlAllowMethods: GET, POST, OPTIONS
# #accessControlAllowHeaders: content-type, x-requested-with, x-ajax, x-token, x-remember
# #accessControlExposeHeaders: x-remember
#
# # 是否允许接收跨域的Cookie凭证数据 CORS
# #accessControlAllowCredentials: false
#
# # 允许的网站来源地址,不设置为全部地址(避免一些跨站点请求伪造 CSRF、防盗链
## allowReferers: http://127.0.0.1,http://localhost
## allowReferers: ~
# #allowReferers: http://127.0.0.1,http://localhost
#
# # 是否在登录后生成新的Session默认false
# isGenerateNewSessionAfterLogin: false
@@ -516,8 +517,11 @@ shiro:
# # 注意如果超时超过30m你还需要同步修改当前配置文件的属性j2cache.caffeine.region.sessionCache 超时时间,大于这个值。
# sessionTimeout: 1800000
#
# # PC设备会话超时参数设置登录请求参数加 param_deviceType=pc 时有效
# #pcSessionTimeout: 1800000
#
# # 手机APP设备会话超时参数设置登录请求参数加 param_deviceType=mobileApp 时有效
# mobileAppSessionTimeout: 43200000
# #mobileAppSessionTimeout: 43200000
#
# # 定时清理失效会话,清理用户直接关闭浏览器造成的孤立会话
# sessionTimeoutClean: 1200000
@@ -528,7 +532,23 @@ shiro:
#
# # 共享的SessionId的Cookie名称保存到跟路径下第三方应用获取。同一域名下多个项目时需设置共享Cookie的名称。
# #shareSessionIdCookieName: ${session.sessionIdCookieName}
#
# # 其它 SimpleCookie 参数v4.2.3
# #sessionIdCookieSecure: false
# #sessionIdCookieHttpOnly: true
# #sessionIdCookieSameSite: LAX
#
# # 设置接收 SessionId 请求参数和请求头的名称
# sessionIdParamName: __sid
# sessionIdHeaderName: x-token
#
# # 当直接通过 __sid 参数浏览器访问页面时,可将直接将 __sid 写入 Cookie 应用于后面的访问
# # 访问地址举例http://host/js/a/index?__sid=123456&__cookie=true
# writeCookieParamName: __cookie
#
# # 记住我的请求参数和请求头的名称v4.2.3
# rememberMeHeaderName: x-remember
#
# 系统缓存配置
#j2cache:
#
@@ -565,6 +585,9 @@ shiro:
# # TypeHandlers 扫描基础包,如果多个,用“,”分隔
# scanTypeHandlersPackage: ~
#
# # 是否开启 JDBC 管理事务,默认 Spring 管理事务 v4.2.3
# jdbcTransaction: false
#
# # Mapper文件刷新线程
# mapper:
# refresh:
@@ -575,6 +598,10 @@ shiro:
# Web 相关
#web:
#
# # AJAX 接受参数名和请求头名v4.3.0
# ajaxParamName: __ajax
# ajaxHeaderName: x-ajax
#
# # MVC 视图相关
# view:
@@ -583,6 +610,16 @@ shiro:
# # 引入页面头部:'/themes/'+themeName+'/include/header.html'
# # 引入页面尾部:'/themes/'+themeName+'/include/footer.html'
# themeName: default
#
# # 使用智能参数接收器,同时支持 JSON 和 FormData 的参数接受
# smartMethodArgumentResolver: true
#
# # 使用 .json、.xml 后缀匹配返回视图数据Spring官方已不推荐使用
# favorPathExtension: false
# # 使用 __ajax=json、__ajax=xml 后缀匹配返回视图数据
# favorParameter: true
# # 使用 x-ajax=json、x-ajax=xml 请求头匹配返回视图数据
# favorHeader: true
#
# # MVC 拦截器
# interceptor:
@@ -628,6 +665,11 @@ shiro:
# id: '[a-zA-Z0-9_\-/#\u4e00-\u9fa5]{0,64}'
# user.loginCode: '[a-zA-Z0-9_\u4e00-\u9fa5]{4,20}'
#
# # 默认不启用(为兼用旧版保留,建议使用 CORS
# jsonp:
# enabled: false
# callback: __callback
#
# # 核心模块的Web功能仅作为微服务时设为false
# core:
# enabled: true
@@ -649,12 +691,12 @@ shiro:
# enabled: true
#
# # 文件上传根路径设置路径中不允许包含“userfiles”在指定目录中系统会自动创建userfiles目录如果不设置默认为contextPath路径
## baseDir: D:/jeesite
# #baseDir: D:/jeesite
#
# # 上传文件的相对路径支持yyyy, MM, dd, HH, mm, ss, E
# uploadPath: '{yyyy}{MM}/'
#
# # 上传单个文件最大字节500M在这之上还有 > Tomcat限制 > Nginx限制
# # 上传单个文件最大字节500M在这之上还有 > Tomcat限制 > Nginx限制,此设置会覆盖 spring.http.multipart.maxFileSize 设置
# maxFileSize: 500*1024*1024
#
# # 设置允许上传的文件后缀(全局设置)
@@ -687,7 +729,7 @@ shiro:
#
# # 视频格式转换 ffmpeg.exe 所放的路径
# ffmpegFile: d:/tools/video/ffmpeg-4.9/bin/ffmpeg.exe
## ffmpegFile: d:/tools/video/libav-10.6-win64/bin/avconv.exe
# #ffmpegFile: d:/tools/video/libav-10.6-win64/bin/avconv.exe
#
# # 视频格式转换 mencoder.exe 所放的路径
# mencoderFile: d:/tools/video/mencoder-4.9/mencoder.exe
@@ -695,6 +737,10 @@ shiro:
# # 将mp4视频的元数据信息转到视频第一帧
# qtFaststartFile: d:/tools/video/qt-faststart/qt-faststart.exe
# 文件管理是否启用租户模式
#filemanager:
# useCorpModel: false
#======================================#
#========== Message settings ==========#
#======================================#
@@ -707,6 +753,8 @@ shiro:
# realtime:
# # 是否开启
# enabled: true
# # 消息实时推送任务Bean名称
# beanName: msgLocalPushTask
# # 推送失败次数,如果推送次数超过了设定次数,仍不成功,则放弃并保存到历史
# pushFailNumber: 3

View File

@@ -56,7 +56,6 @@
headerHeight = $('.box-header').outerHeight() || 0,
footerHeight = $('.box-footer').outerHeight() || 0,
height = windowHeight - headerHeight - footerHeight - 13;
log(height)
return height < 300 ? 300 : height;
}
});