From 7feeed50155bb1efbcf00f466385e6b3dc8fda64 Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Tue, 21 Feb 2023 11:39:46 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix(=E4=BB=AA=E8=A1=A8=E6=9D=BF):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E6=98=8E=E7=BB=86=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E6=97=A0=E6=B3=95=E6=BB=9A=E5=8A=A8=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/canvas/customComponent/UserViewDialog.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/canvas/customComponent/UserViewDialog.vue b/frontend/src/components/canvas/customComponent/UserViewDialog.vue index a3a4d023ce..58a4e5fee1 100644 --- a/frontend/src/components/canvas/customComponent/UserViewDialog.vue +++ b/frontend/src/components/canvas/customComponent/UserViewDialog.vue @@ -64,7 +64,7 @@ :enable-scroll="false" :chart="chartTable" :show-summary="false" - class="table-class" + class="table-class-dialog" /> @@ -342,8 +342,9 @@ export default { height: 100%; } -.table-class { +.table-class-dialog { height: 100%; + overflow-y: auto !important; } .canvas-class { From 2658cc4cef5ede5b6bf0d9c369b244d5c455f531 Mon Sep 17 00:00:00 2001 From: junjun Date: Tue, 21 Feb 2023 11:58:43 +0800 Subject: [PATCH 2/7] =?UTF-8?q?fix(=E8=A7=86=E5=9B=BE):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=98=8E=E7=BB=86=E8=A1=A8=E6=9F=A5=E8=AF=A2=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E5=A4=B1=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/canvas/customComponent/UserView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/canvas/customComponent/UserView.vue b/frontend/src/components/canvas/customComponent/UserView.vue index da4713b75f..e5de90d083 100644 --- a/frontend/src/components/canvas/customComponent/UserView.vue +++ b/frontend/src/components/canvas/customComponent/UserView.vue @@ -759,7 +759,7 @@ export default { const attrSize = JSON.parse(this.view.customAttr).size if (this.chart.type === 'table-info' && this.view.datasetMode === 0 && (!attrSize.tablePageMode || attrSize.tablePageMode === 'page')) { requestInfo.goPage = this.currentPage.page - requestInfo.pageSize = this.currentPage.pageSize + requestInfo.pageSize = this.currentPage.pageSize === parseInt(attrSize.tablePageSize) ? this.currentPage.pageSize : parseInt(attrSize.tablePageSize) } } if (this.isFirstLoad) { From 203ed10aa393e23bc56ba82fec6337f77e559f2f Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 21 Feb 2023 12:43:50 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(=E7=A7=BB=E5=8A=A8=E7=AB=AF):=20?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E5=88=A0=E9=99=A4=E7=BC=93=E5=AD=98=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E6=9C=AA=E7=BB=91=E5=AE=9A=E4=B9=9F=E8=83=BD=E4=BB=8E?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E5=8F=B0=E8=BF=9B=E5=85=A5DE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/permission.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/permission.js b/frontend/src/permission.js index c612f949c9..96aa5902fd 100644 --- a/frontend/src/permission.js +++ b/frontend/src/permission.js @@ -57,7 +57,7 @@ const routeBefore = (callBack) => { callBack() } } -router.beforeEach(async(to, from, next) => routeBefore(() => { +router.beforeEach(async (to, from, next) => routeBefore(() => { // start progress bar NProgress.start() const mobileIgnores = ['/delink', '/de-auto-login'] @@ -69,6 +69,9 @@ router.beforeEach(async(to, from, next) => routeBefore(() => { if (hasToken) { urlSuffix += ('?detoken=' + hasToken) } + localStorage.removeItem('user-info') + localStorage.removeItem('userId') + localStorage.removeItem('Authorization') window.location.href = window.origin + urlSuffix NProgress.done() } From ee6697a5b9c4acea1ff89f99664d531971482a8c Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Tue, 21 Feb 2023 13:57:53 +0800 Subject: [PATCH 4/7] =?UTF-8?q?refactor:=20=E4=BB=AA=E8=A1=A8=E6=9D=BF?= =?UTF-8?q?=E9=98=B2=E8=8C=83XSS=E6=94=BB=E5=87=BB=20#4585?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 3 ++- .../src/components/canvas/customComponent/DeRichText.vue | 3 ++- .../components/canvas/customComponent/DeRichTextView.vue | 3 ++- frontend/src/components/canvas/customComponent/VText.vue | 8 ++++---- frontend/src/main.js | 6 ++++++ 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 3816f0a7ab..1a2b29da57 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -88,7 +88,8 @@ "vuedraggable": "^2.24.3", "vuex": "3.1.0", "webpack": "^4.46.0", - "xlsx": "^0.17.0" + "xlsx": "^0.17.0", + "xss": "^1.0.14" }, "devDependencies": { "@babel/core": "^7.4.0-0", diff --git a/frontend/src/components/canvas/customComponent/DeRichText.vue b/frontend/src/components/canvas/customComponent/DeRichText.vue index 4e5a76ab38..195a4bc263 100644 --- a/frontend/src/components/canvas/customComponent/DeRichText.vue +++ b/frontend/src/components/canvas/customComponent/DeRichText.vue @@ -37,6 +37,7 @@ import 'tinymce/plugins/nonbreaking' import 'tinymce/plugins/pagebreak' import { mapState } from 'vuex' import Vue from 'vue' +import xssCheck from 'xss' export default { name: 'DeRichText', @@ -77,7 +78,7 @@ export default { canEdit: false, // 初始化配置 tinymceId: 'tinymce-' + this.element.id, - myValue: this.propValue, + myValue: xssCheck(this.propValue), init: { selector: '#tinymce-' + this.element.id, toolbar_items_size: 'small', diff --git a/frontend/src/components/canvas/customComponent/DeRichTextView.vue b/frontend/src/components/canvas/customComponent/DeRichTextView.vue index 7b5f717876..fe66736ee2 100644 --- a/frontend/src/components/canvas/customComponent/DeRichTextView.vue +++ b/frontend/src/components/canvas/customComponent/DeRichTextView.vue @@ -38,6 +38,7 @@ import 'tinymce/plugins/pagebreak' import { mapState } from 'vuex' import bus from '@/utils/bus' import { uuid } from 'vue-uuid' +import xssCheck from 'xss' export default { name: 'DeRichTextView', @@ -152,7 +153,7 @@ export default { viewInit() { bus.$on('fieldSelect-' + this.element.propValue.viewId, this.fieldSelect) tinymce.init({}) - this.myValue = this.assignment(this.element.propValue.textValue) + this.myValue = xssCheck(this.assignment(this.element.propValue.textValue)) bus.$on('initCurFields-' + this.element.id, this.initCurFieldsChange) this.$nextTick(() => { this.initReady = true diff --git a/frontend/src/components/canvas/customComponent/VText.vue b/frontend/src/components/canvas/customComponent/VText.vue index f23c2ca559..8dbd863c42 100644 --- a/frontend/src/components/canvas/customComponent/VText.vue +++ b/frontend/src/components/canvas/customComponent/VText.vue @@ -18,7 +18,7 @@ @mousedown="handleMousedown" @blur="handleBlur" @input="handleInput" - v-html="element.propValue" + v-html="$xss(element.propValue)" />
@@ -80,7 +80,7 @@ export default { }, textInfo() { if (this.element && this.element.hyperlinks && this.element.hyperlinks.enable) { - return "" + this.element.propValue + '' + return '' + this.element.propValue + '' } else { return this.element.propValue } diff --git a/frontend/src/main.js b/frontend/src/main.js index 459f66280a..673cf928ec 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -43,6 +43,12 @@ import 'video.js/dist/video-js.css' // 控制标签宽高成比例的指令 import proportion from 'vue-proportion-directive' +import xss from 'xss' +// 定义全局XSS解决方法 +Object.defineProperty(Vue.prototype, '$xss', { + value: xss +}) + Vue.config.productionTip = false Vue.use(VueClipboard) Vue.use(widgets) From d9cfc4dfc50e0d1676b74db787837860b91d65de Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 21 Feb 2023 14:05:36 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix(=E8=B7=AF=E7=94=B1):=20=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=B7=AF=E7=94=B1=E5=88=B0=E8=B5=84=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/permission.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/permission.js b/frontend/src/permission.js index 96aa5902fd..efcede886b 100644 --- a/frontend/src/permission.js +++ b/frontend/src/permission.js @@ -130,7 +130,7 @@ router.beforeEach(async (to, from, next) => routeBefore(() => { next() } else { // other pages that do not have permission to access are redirected to the login page. - next(`/login?redirect=${to.path}`) + next(`/login?redirect=${to.fullPath}`) NProgress.done() } } From 6bb338a36433a24a9044f2030f445507d65cc4c3 Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Tue, 21 Feb 2023 14:41:22 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix(=E4=BB=AA=E8=A1=A8=E7=89=88):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=BE=91=E7=8A=B6=E6=80=81=E4=B8=8B?= =?UTF-8?q?Tab=E7=BB=84=E4=BB=B6=E5=86=85=E9=83=A8=E4=BB=AA=E8=A1=A8?= =?UTF-8?q?=E6=9D=BF=E6=9D=BF=E5=88=87=E6=8D=A2=E6=97=B6=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=84=E9=94=99=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/widget/deWidget/DeTabs.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/components/widget/deWidget/DeTabs.vue b/frontend/src/components/widget/deWidget/DeTabs.vue index 3e9fe23856..786622fa4e 100644 --- a/frontend/src/components/widget/deWidget/DeTabs.vue +++ b/frontend/src/components/widget/deWidget/DeTabs.vue @@ -411,6 +411,10 @@ export default { const _this = this _this.$nextTick(() => { try { + const targetRef = _this.$refs['canvasTabRef-' + _this.activeTabName] + if (targetRef) { + targetRef[0].restore() + } _this.$refs[this.activeTabName][0].resizeChart() } catch (e) { // ignore From ac4bf63a8949a92e00cbdf4a8f7651fac7c9ae41 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 21 Feb 2023 16:35:27 +0800 Subject: [PATCH 7/7] =?UTF-8?q?perf(token):=20=E7=A6=81=E7=94=A8=E6=AF=8F?= =?UTF-8?q?=E5=88=86=E9=92=9F=E8=87=AA=E5=8A=A8=E5=88=B7=E6=96=B0token?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/dataease/auth/filter/F2CDocFilter.java | 21 +----- .../io/dataease/auth/filter/JWTFilter.java | 46 ++----------- .../java/io/dataease/auth/util/JWTUtils.java | 67 ++----------------- .../commons/utils/TokenCacheUtils.java | 5 +- .../ApplicationCloseEventListener.java | 24 +++++++ .../io/dataease/listener/util/CacheUtils.java | 6 ++ .../src/main/resources/ehcache/ehcache.xml | 14 ++-- 7 files changed, 55 insertions(+), 128 deletions(-) create mode 100644 backend/src/main/java/io/dataease/listener/ApplicationCloseEventListener.java diff --git a/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java index d5d8438c3a..ef1c304810 100644 --- a/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java @@ -79,12 +79,7 @@ public class F2CDocFilter extends AccessControlFilter { if (StringUtils.isBlank(authorization)) { return false; } - if (JWTUtils.loginExpire(authorization)) { - return false; - } - if (JWTUtils.needRefresh(authorization)) { - authorization = refreshToken(authorization); - } + TokenInfo tokenInfo = JWTUtils.tokenInfoByToken(authorization); AuthUserService authUserService = CommonBeanFactory.getBean(AuthUserService.class); SysUserEntity user = authUserService.getUserById(tokenInfo.getUserId()); @@ -96,20 +91,6 @@ public class F2CDocFilter extends AccessControlFilter { return verify; } - private String refreshToken(String token) throws Exception { - TokenInfo tokenInfo = JWTUtils.tokenInfoByToken(token); - AuthUserService authUserService = CommonBeanFactory.getBean(AuthUserService.class); - SysUserEntity user = authUserService.getUserById(tokenInfo.getUserId()); - if (user == null) { - DataEaseException.throwException(Translator.get("i18n_not_find_user")); - } - String password = user.getPassword(); - Algorithm algorithm = Algorithm.HMAC256(password); - JWTUtils.verifySign(algorithm, token); - String newToken = JWTUtils.sign(tokenInfo, password); - return newToken; - } - @Override protected boolean onAccessDenied(ServletRequest req, ServletResponse res) throws Exception { HttpServletResponse response = (HttpServletResponse) res; diff --git a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java index 0d70181289..83c73fc1ca 100644 --- a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java @@ -1,24 +1,18 @@ package io.dataease.auth.filter; -import com.auth0.jwt.algorithms.Algorithm; import io.dataease.auth.entity.ASKToken; import io.dataease.auth.entity.JWTToken; -import io.dataease.auth.entity.SysUserEntity; -import io.dataease.auth.entity.TokenInfo; + import io.dataease.auth.handler.ApiKeyHandler; -import io.dataease.auth.service.AuthUserService; -import io.dataease.auth.util.JWTUtils; -import io.dataease.commons.utils.CommonBeanFactory; + import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.TokenCacheUtils; -import io.dataease.exception.DataEaseException; -import io.dataease.i18n.Translator; + import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RequestMethod; @@ -30,7 +24,6 @@ import javax.servlet.http.HttpServletResponse; public class JWTFilter extends BasicHttpAuthenticationFilter { - private Logger LOGGER = LoggerFactory.getLogger(this.getClass()); public final static String expireMessage = "Login token is expire."; @@ -69,14 +62,7 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { if (TokenCacheUtils.invalid(authorization)) { throw new AuthenticationException(expireMessage); } - // 当没有出现登录超时 且需要刷新token 则执行刷新token - if (JWTUtils.loginExpire(authorization)) { - TokenCacheUtils.remove(authorization); - throw new AuthenticationException(expireMessage); - } - if (JWTUtils.needRefresh(authorization)) { - authorization = refreshToken(request, response); - } + JWTToken token = new JWTToken(authorization); Subject subject = getSubject(request, response); // 提交给realm进行登入,如果错误他会抛出异常并被捕获 @@ -110,28 +96,6 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { } - private String refreshToken(ServletRequest request, ServletResponse response) throws Exception { - // 获取AccessToken(Shiro中getAuthzHeader方法已经实现) - String token = this.getAuthzHeader(request); - // 获取当前Token的帐号信息 - TokenInfo tokenInfo = JWTUtils.tokenInfoByToken(token); - AuthUserService authUserService = CommonBeanFactory.getBean(AuthUserService.class); - SysUserEntity user = authUserService.getUserById(tokenInfo.getUserId()); - if (user == null) { - DataEaseException.throwException(Translator.get("i18n_not_find_user")); - } - String password = user.getPassword(); - Algorithm algorithm = Algorithm.HMAC256(password); - JWTUtils.verifySign(algorithm, token); - String newToken = JWTUtils.sign(tokenInfo, password); - // 设置响应的Header头新Token - HttpServletResponse httpServletResponse = (HttpServletResponse) response; - httpServletResponse.addHeader("Access-Control-Expose-Headers", "RefreshAuthorization"); - httpServletResponse.setHeader("RefreshAuthorization", newToken); - return newToken; - } - - /** * 对跨域提供支持 */ diff --git a/backend/src/main/java/io/dataease/auth/util/JWTUtils.java b/backend/src/main/java/io/dataease/auth/util/JWTUtils.java index fc297d1e17..a541433842 100644 --- a/backend/src/main/java/io/dataease/auth/util/JWTUtils.java +++ b/backend/src/main/java/io/dataease/auth/util/JWTUtils.java @@ -4,7 +4,6 @@ import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.JWTCreator.Builder; import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.Verification; import io.dataease.auth.entity.TokenInfo; @@ -19,10 +18,8 @@ import java.util.Date; public class JWTUtils { - // token过期时间1min (过期会自动刷新续命 目的是避免一直都是同一个token ) - private static final long EXPIRE_TIME = 1 * 60 * 1000; - // 登录间隔时间10min 超过这个时间强制重新登录 - private static long Login_Interval; + + private static Long expireTime; /** * 校验token是否正确 @@ -65,62 +62,24 @@ public class JWTUtils { return tokenInfoBuilder.build(); } - public static boolean needRefresh(String token) { - Date exp = JWTUtils.getExp(token); - Long advanceTime = 5000L; - return (new Date().getTime() + advanceTime) >= exp.getTime(); - } - /** - * 当前token是否登录超时 - * - * @param token - * @return - */ - public static boolean loginExpire(String token) { - if (Login_Interval == 0) { - // 默认超时时间是8h - Long minute = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Long.class, - 8 * 60L); - // 分钟换算成毫秒 - Login_Interval = minute * 1000 * 60; - } - Long lastOperateTime = tokenLastOperateTime(token); - boolean isExpire = true; - if (lastOperateTime != null) { - Long now = System.currentTimeMillis(); - isExpire = now - lastOperateTime > Login_Interval; - } - return isExpire; - } - - public static Date getExp(String token) { - try { - DecodedJWT jwt = JWT.decode(token); - return jwt.getClaim("exp").asDate(); - } catch (JWTDecodeException e) { - e.printStackTrace(); - return null; - } - } - - /** - * 生成签名,5min后过期 - * * @param tokenInfo 用户信息 * @param secret 用户的密码 * @return 加密的token */ public static String sign(TokenInfo tokenInfo, String secret) { try { - Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); + if (ObjectUtils.isEmpty(expireTime)) { + expireTime = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Long.class, 480L); + } + long expireTimeMillis = expireTime * 60000L; + Date date = new Date(System.currentTimeMillis() + expireTimeMillis); Algorithm algorithm = Algorithm.HMAC256(secret); Builder builder = JWT.create() .withClaim("username", tokenInfo.getUsername()) .withClaim("userId", tokenInfo.getUserId()); String sign = builder.withExpiresAt(date).sign(algorithm); return sign; - } catch (Exception e) { return null; } @@ -143,7 +102,6 @@ public class JWTUtils { } else { verifier = JWT.require(algorithm).withClaim("resourceId", resourceId).withClaim("userId", userId).build(); } - try { verifier.verify(token); return true; @@ -152,16 +110,5 @@ public class JWTUtils { } } - /** - * 获取当前token上次操作时间 - * - * @param token - * @return - */ - public static Long tokenLastOperateTime(String token) { - DecodedJWT jwt = JWT.decode(token); - Date expiresAt = jwt.getExpiresAt(); - return expiresAt.getTime(); - } } diff --git a/backend/src/main/java/io/dataease/commons/utils/TokenCacheUtils.java b/backend/src/main/java/io/dataease/commons/utils/TokenCacheUtils.java index 0bcec3b8c8..32b68267ab 100644 --- a/backend/src/main/java/io/dataease/commons/utils/TokenCacheUtils.java +++ b/backend/src/main/java/io/dataease/commons/utils/TokenCacheUtils.java @@ -50,8 +50,9 @@ public class TokenCacheUtils { } Long time = expTime * 60; - CacheUtils.put(KEY, token, userId, time.intValue(), null); - + Double v = time * 0.6; + CacheUtils.put(KEY, token, userId, time.intValue(), v.intValue()); + CacheUtils.flush(KEY); } public static void remove(String token) { diff --git a/backend/src/main/java/io/dataease/listener/ApplicationCloseEventListener.java b/backend/src/main/java/io/dataease/listener/ApplicationCloseEventListener.java new file mode 100644 index 0000000000..4fde79311f --- /dev/null +++ b/backend/src/main/java/io/dataease/listener/ApplicationCloseEventListener.java @@ -0,0 +1,24 @@ +package io.dataease.listener; + +import io.dataease.commons.utils.LogUtil; +import net.sf.ehcache.CacheManager; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.stereotype.Component; + +@Component +public class ApplicationCloseEventListener implements ApplicationListener { + + @Autowired(required = false) + CacheManager cacheManager; + + @Override + public void onApplicationEvent(ContextClosedEvent event) { + + if (ObjectUtils.isNotEmpty(cacheManager)) + cacheManager.shutdown(); + LogUtil.info("DataEase is stopping"); + } +} diff --git a/backend/src/main/java/io/dataease/listener/util/CacheUtils.java b/backend/src/main/java/io/dataease/listener/util/CacheUtils.java index 22ebed424a..9a4fd3aa88 100644 --- a/backend/src/main/java/io/dataease/listener/util/CacheUtils.java +++ b/backend/src/main/java/io/dataease/listener/util/CacheUtils.java @@ -66,6 +66,12 @@ public class CacheUtils { return cache(cacheName).remove(key); } + public static void flush(String cacheName) { + CacheManager manager = getCacheManager(); + if (manager instanceof RedisCacheManager) return; + cache(cacheName).flush(); + } + public static void removeAll(String cacheName) { if (getCacheManager() instanceof RedisCacheManager) { org.springframework.cache.Cache cache = getCacheManager().getCache(cacheName); diff --git a/backend/src/main/resources/ehcache/ehcache.xml b/backend/src/main/resources/ehcache/ehcache.xml index 5976911a62..144cdb7ad6 100644 --- a/backend/src/main/resources/ehcache/ehcache.xml +++ b/backend/src/main/resources/ehcache/ehcache.xml @@ -272,12 +272,16 @@ + timeToIdleSeconds="28800" + timeToLiveSeconds="28800" + memoryStoreEvictionPolicy="LRU" + diskPersistent="true"> + +