From e5941ee58b78f95d0843985f55b50d0ed4dd8176 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Wed, 10 Mar 2021 14:25:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=95=BF=E6=97=B6=E9=97=B4=E6=97=A0?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=88=99token=E8=87=AA=E5=8A=A8=E5=A4=B1?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/dataease/auth/filter/JWTFilter.java | 29 +++++++++++++++++-- .../java/io/dataease/auth/util/JWTUtils.java | 26 +++++++---------- frontend/src/lang/zh.js | 4 ++- frontend/src/store/modules/user.js | 7 +++++ frontend/src/utils/message.js | 10 +++---- frontend/src/utils/request.js | 13 +++++---- frontend/src/views/login/index.vue | 8 +++-- 7 files changed, 67 insertions(+), 30 deletions(-) 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 3d05e91831..314803d371 100644 --- a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java @@ -6,6 +6,9 @@ import io.dataease.auth.entity.TokenInfo; import io.dataease.auth.service.AuthUserService; import io.dataease.auth.util.JWTUtils; import io.dataease.commons.utils.CommonBeanFactory; +import io.dataease.commons.utils.ServletUtils; +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; @@ -23,6 +26,8 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { private Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + public final static String expireMessage = "login token is expire"; + /*@Autowired private AuthUserService authUserService;*/ @@ -46,7 +51,10 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String authorization = httpServletRequest.getHeader("Authorization"); // 当没有出现登录超时 且需要刷新token 则执行刷新token - if (!JWTUtils.loginExpire(authorization) && JWTUtils.needRefresh(authorization)){ + if (JWTUtils.loginExpire(authorization)){ + throw new AuthenticationException(expireMessage); + } + if (JWTUtils.needRefresh(authorization)){ authorization = refreshToken(request, response); } JWTToken token = new JWTToken(authorization); @@ -67,7 +75,12 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { boolean loginSuccess = executeLogin(request, response); return loginSuccess; } catch (Exception e) { - response401(request, response); + if (e instanceof AuthenticationException && StringUtils.equals(e.getMessage(), expireMessage)){ + responseExpire(request, response); + }else { + response401(request, response); + } + } } return false; @@ -129,4 +142,16 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { LOGGER.error(e.getMessage()); } } + + private void responseExpire(ServletRequest req, ServletResponse resp) { + try { + HttpServletResponse httpServletResponse = (HttpServletResponse) resp; + httpServletResponse.addHeader("Access-Control-Expose-Headers", "authentication-status"); + httpServletResponse.setHeader("authentication-status", "login_expire"); + httpServletResponse.setStatus(401); + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + } + } 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 a52c4d2485..b43ae98bd3 100644 --- a/backend/src/main/java/io/dataease/auth/util/JWTUtils.java +++ b/backend/src/main/java/io/dataease/auth/util/JWTUtils.java @@ -6,23 +6,23 @@ import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import io.dataease.auth.entity.TokenInfo; +import io.dataease.auth.filter.JWTFilter; import io.dataease.commons.utils.CommonBeanFactory; -import io.dataease.commons.utils.ServletUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authc.AuthenticationException; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; -import javax.servlet.http.HttpServletResponse; import java.util.Date; public class JWTUtils { - // token过期时间5min (过期会自动刷新续命 目的是避免一直都是同一个token ) - private static final long EXPIRE_TIME = 1*60*1000; + // token过期时间1min (过期会自动刷新续命 目的是避免一直都是同一个token ) + private static final long EXPIRE_TIME = 1*60*1000/2; // 登录间隔时间10min 超过这个时间强制重新登录 - private static final long Login_Interval = 2*60*1000; + private static final long Login_Interval = 20*60*1000; /** @@ -38,17 +38,12 @@ public class JWTUtils { .withClaim("username", tokenInfo.getUsername()) .withClaim("userId", tokenInfo.getUserId()) .build(); - DecodedJWT jwt = verifier.verify(token); - //Long lastLoginTime = jwt.getClaim("lastLoginTime").asLong(); - Long lastOperateTime = tokenLastOperateTime(token); - long now = System.currentTimeMillis(); - if (now - lastOperateTime > Login_Interval){ + verifier.verify(token); + if (loginExpire(token)){ // 登录超时 - HttpServletResponse response = ServletUtils.response(); - response.addHeader("Access-Control-Expose-Headers", "authentication-status"); - response.setHeader("authentication-status", "login_expire"); + throw new AuthenticationException(JWTFilter.expireMessage); // 前端拦截 登录超时状态 直接logout - return false; + //return false; } return true; } @@ -143,6 +138,7 @@ public class JWTUtils { public static void addTokenExpire(String token){ CacheManager cacheManager = CommonBeanFactory.getBean(CacheManager.class); Cache tokens_expire = cacheManager.getCache("tokens_expire"); - tokens_expire.put(token, System.currentTimeMillis()); + long now = System.currentTimeMillis(); + tokens_expire.put(token, now); } } diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index c70fce5650..07f0a2e694 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -80,7 +80,9 @@ export default { password: '密码', any: '随便填', thirdparty: '第三方登录', - thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!' + thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!', + expires: '登录token过期,请重新登录', + tokenError: 'token错误,请重新登录' }, commons: { upload: '上传', diff --git a/frontend/src/store/modules/user.js b/frontend/src/store/modules/user.js index ab250c4e0f..2ceab1fc30 100644 --- a/frontend/src/store/modules/user.js +++ b/frontend/src/store/modules/user.js @@ -42,6 +42,9 @@ const mutations = { }, SET_PERMISSIONS: (state, permissions) => { state.permissions = permissions + }, + SET_LOGIN_MSG: (state, msg) => { + state.loginMsg = msg } } @@ -53,6 +56,7 @@ const actions = { login({ username: username.trim(), password: password }).then(response => { const { data } = response commit('SET_TOKEN', data.token) + commit('SET_LOGIN_MSG', null) setToken(data.token) resolve() }).catch(error => { @@ -117,6 +121,9 @@ const actions = { commit('RESET_STATE') resolve() }) + }, + setLoginMsg({ commit, msg }) { + commit('SET_LOGIN_MSG', msg) } } diff --git a/frontend/src/utils/message.js b/frontend/src/utils/message.js index dc0d92f324..6fb5c6d1cc 100644 --- a/frontend/src/utils/message.js +++ b/frontend/src/utils/message.js @@ -1,7 +1,7 @@ import { MessageBox, Message } from 'element-ui' - +import i18n from '@/lang' export const $alert = (message, callback, options) => { - const title = this.$t('common.message_box.alert') + const title = i18n.t('common.message_box.alert') MessageBox.alert(message, title, options).then(() => { callback() }) @@ -9,12 +9,12 @@ export const $alert = (message, callback, options) => { export const $confirm = (message, callback, options = {}) => { const defaultOptions = { - confirmButtonText: this.$t('common.button.ok'), - cancelButtonText: this.$t('common.button.cancel'), + confirmButtonText: i18n.t('common.button.ok'), + cancelButtonText: i18n.t('common.button.cancel'), type: 'warning', ...options } - const title = this.$t('common.message_box.confirm') + const title = i18n.t('common.message_box.confirm') MessageBox.confirm(message, title, defaultOptions).then(() => { callback() }) diff --git a/frontend/src/utils/request.js b/frontend/src/utils/request.js index 2a93f3eab2..7232afaea8 100644 --- a/frontend/src/utils/request.js +++ b/frontend/src/utils/request.js @@ -4,7 +4,7 @@ import store from '@/store' import { $alert, $error } from './message' import { getToken } from '@/utils/auth' import Config from '@/settings' - +import i18n from '@/lang' import { tryShowLoading, tryHideLoading } from './loading' // import router from '@/router' @@ -44,16 +44,19 @@ service.interceptors.request.use( const checkAuth = response => { // 请根据实际需求修改 - if (response.headers['authentication-status'] === 'invalid' || response.status === 401) { - const message = this.$t('login.expires') + + if (response.headers['authentication-status'] === 'login_expire') { + const message = i18n.t('login.expires') + store.dispatch('user/setLoginMsg', message) $alert(message, () => { store.dispatch('user/logout').then(() => { location.reload() }) }) } - if (response.headers['authentication-status'] === 'login_expire') { - const message = this.$t('login.expires') + + if (response.headers['authentication-status'] === 'invalid' || response.status === 401) { + const message = i18n.t('login.tokenError') $alert(message, () => { store.dispatch('user/logout').then(() => { location.reload() diff --git a/frontend/src/views/login/index.vue b/frontend/src/views/login/index.vue index 891b3f5b8b..443529cba8 100644 --- a/frontend/src/views/login/index.vue +++ b/frontend/src/views/login/index.vue @@ -79,8 +79,12 @@ export default { }, loading: false, passwordType: 'password', - redirect: undefined, - msg: null + redirect: undefined + } + }, + computed: { + msg() { + return this.$store.state.user.loginMsg } }, watch: {