Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
D
dataease
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
zhu
dataease
Commits
e5941ee5
提交
e5941ee5
authored
3月 10, 2021
作者:
fit2cloud-chenyw
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 长时间无操作则token自动失效
上级
2a766461
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
67 行增加
和
30 行删除
+67
-30
JWTFilter.java
backend/src/main/java/io/dataease/auth/filter/JWTFilter.java
+27
-2
JWTUtils.java
backend/src/main/java/io/dataease/auth/util/JWTUtils.java
+11
-15
zh.js
frontend/src/lang/zh.js
+3
-1
user.js
frontend/src/store/modules/user.js
+7
-0
message.js
frontend/src/utils/message.js
+5
-5
request.js
frontend/src/utils/request.js
+8
-5
index.vue
frontend/src/views/login/index.vue
+6
-2
没有找到文件。
backend/src/main/java/io/dataease/auth/filter/JWTFilter.java
浏览文件 @
e5941ee5
...
...
@@ -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
());
}
}
}
backend/src/main/java/io/dataease/auth/util/JWTUtils.java
浏览文件 @
e5941ee5
...
...
@@ -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过期时间
5
min (过期会自动刷新续命 目的是避免一直都是同一个token )
private
static
final
long
EXPIRE_TIME
=
1
*
60
*
1000
;
// token过期时间
1
min (过期会自动刷新续命 目的是避免一直都是同一个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
=
2
0
*
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
);
}
}
frontend/src/lang/zh.js
浏览文件 @
e5941ee5
...
...
@@ -80,7 +80,9 @@ export default {
password
:
'密码'
,
any
:
'随便填'
,
thirdparty
:
'第三方登录'
,
thirdpartyTips
:
'本地不能模拟,请结合自己业务进行模拟!!!'
thirdpartyTips
:
'本地不能模拟,请结合自己业务进行模拟!!!'
,
expires
:
'登录token过期,请重新登录'
,
tokenError
:
'token错误,请重新登录'
},
commons
:
{
upload
:
'上传'
,
...
...
frontend/src/store/modules/user.js
浏览文件 @
e5941ee5
...
...
@@ -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
)
}
}
...
...
frontend/src/utils/message.js
浏览文件 @
e5941ee5
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
()
})
...
...
frontend/src/utils/request.js
浏览文件 @
e5941ee5
...
...
@@ -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
()
...
...
frontend/src/views/login/index.vue
浏览文件 @
e5941ee5
...
...
@@ -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
:
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论