Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Eladmin
Commits
284c25a1
Commit
284c25a1
authored
Dec 01, 2019
by
dqjdda
Browse files
Merge branch '2.4dev' into 2.4opt
parents
175a2eb6
ccca30fc
Changes
48
Hide whitespace changes
Inline
Side-by-side
eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAccessDeniedHandler.java
0 → 100644
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
import
org.springframework.security.access.AccessDeniedException
;
import
org.springframework.security.web.access.AccessDeniedHandler
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Zheng Jie
*/
@Component
public
class
JwtAccessDeniedHandler
implements
AccessDeniedHandler
{
@Override
public
void
handle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AccessDeniedException
accessDeniedException
)
throws
IOException
{
//当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
,
accessDeniedException
.
getMessage
());
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java
View file @
284c25a1
...
...
@@ -13,9 +13,7 @@ import java.io.Serializable;
* @author Zheng Jie
*/
@Component
public
class
JwtAuthenticationEntryPoint
implements
AuthenticationEntryPoint
,
Serializable
{
private
static
final
long
serialVersionUID
=
-
8970718410437077606L
;
public
class
JwtAuthenticationEntryPoint
implements
AuthenticationEntryPoint
{
@Override
public
void
commence
(
HttpServletRequest
request
,
...
...
eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java
deleted
100644 → 0
View file @
175a2eb6
package
me.zhengjie.modules.security.security
;
import
io.jsonwebtoken.ExpiredJwtException
;
import
lombok.extern.slf4j.Slf4j
;
import
me.zhengjie.modules.security.utils.JwtTokenUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.web.authentication.WebAuthenticationDetailsSource
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Zheng Jie
*/
@Slf4j
@Component
public
class
JwtAuthorizationTokenFilter
extends
OncePerRequestFilter
{
@Value
(
"${jwt.online}"
)
private
String
onlineKey
;
private
final
UserDetailsService
userDetailsService
;
private
final
JwtTokenUtil
jwtTokenUtil
;
private
final
RedisTemplate
redisTemplate
;
public
JwtAuthorizationTokenFilter
(
@Qualifier
(
"jwtUserDetailsServiceImpl"
)
UserDetailsService
userDetailsService
,
JwtTokenUtil
jwtTokenUtil
,
RedisTemplate
redisTemplate
)
{
this
.
userDetailsService
=
userDetailsService
;
this
.
jwtTokenUtil
=
jwtTokenUtil
;
this
.
redisTemplate
=
redisTemplate
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
chain
)
throws
ServletException
,
IOException
{
String
authToken
=
jwtTokenUtil
.
getToken
(
request
);
OnlineUser
onlineUser
=
null
;
try
{
onlineUser
=
(
OnlineUser
)
redisTemplate
.
opsForValue
().
get
(
onlineKey
+
authToken
);
}
catch
(
ExpiredJwtException
e
)
{
log
.
error
(
e
.
getMessage
());
}
if
(
onlineUser
!=
null
&&
SecurityContextHolder
.
getContext
().
getAuthentication
()
==
null
)
{
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
JwtUser
userDetails
=
(
JwtUser
)
this
.
userDetailsService
.
loadUserByUsername
(
onlineUser
.
getUserName
());
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if
(
jwtTokenUtil
.
validateToken
(
authToken
,
userDetails
))
{
UsernamePasswordAuthenticationToken
authentication
=
new
UsernamePasswordAuthenticationToken
(
userDetails
,
null
,
userDetails
.
getAuthorities
());
authentication
.
setDetails
(
new
WebAuthenticationDetailsSource
().
buildDetails
(
request
));
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
}
}
chain
.
doFilter
(
request
,
response
);
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenConfigurer.java
0 → 100644
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
import
org.springframework.security.config.annotation.SecurityConfigurerAdapter
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.web.DefaultSecurityFilterChain
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
/**
* @author /
*/
public
class
TokenConfigurer
extends
SecurityConfigurerAdapter
<
DefaultSecurityFilterChain
,
HttpSecurity
>
{
private
final
TokenProvider
tokenProvider
;
public
TokenConfigurer
(
TokenProvider
tokenProvider
){
this
.
tokenProvider
=
tokenProvider
;
}
@Override
public
void
configure
(
HttpSecurity
http
)
{
TokenFilter
customFilter
=
new
TokenFilter
(
tokenProvider
);
http
.
addFilterBefore
(
customFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenFilter.java
0 → 100644
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
import
io.jsonwebtoken.ExpiredJwtException
;
import
lombok.extern.slf4j.Slf4j
;
import
me.zhengjie.modules.security.config.SecurityProperties
;
import
me.zhengjie.modules.security.security.vo.OnlineUser
;
import
me.zhengjie.modules.security.service.OnlineUserService
;
import
me.zhengjie.utils.SpringContextHolder
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.filter.GenericFilterBean
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.IOException
;
/**
* @author /
*/
@Slf4j
public
class
TokenFilter
extends
GenericFilterBean
{
private
final
TokenProvider
tokenProvider
;
TokenFilter
(
TokenProvider
tokenProvider
)
{
this
.
tokenProvider
=
tokenProvider
;
}
@Override
public
void
doFilter
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
HttpServletRequest
httpServletRequest
=
(
HttpServletRequest
)
servletRequest
;
String
token
=
resolveToken
(
httpServletRequest
);
String
requestRri
=
httpServletRequest
.
getRequestURI
();
// 验证 token 是否存在
OnlineUser
onlineUser
=
null
;
try
{
SecurityProperties
properties
=
SpringContextHolder
.
getBean
(
SecurityProperties
.
class
);
OnlineUserService
onlineUserService
=
SpringContextHolder
.
getBean
(
OnlineUserService
.
class
);
onlineUser
=
onlineUserService
.
getOne
(
properties
.
getOnlineKey
()
+
token
);
}
catch
(
ExpiredJwtException
e
)
{
log
.
error
(
e
.
getMessage
());
}
if
(
onlineUser
!=
null
&&
StringUtils
.
hasText
(
token
)
&&
tokenProvider
.
validateToken
(
token
))
{
Authentication
authentication
=
tokenProvider
.
getAuthentication
(
token
);
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
log
.
debug
(
"set Authentication to security context for '{}', uri: {}"
,
authentication
.
getName
(),
requestRri
);
}
else
{
log
.
debug
(
"no valid JWT token found, uri: {}"
,
requestRri
);
}
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
}
private
String
resolveToken
(
HttpServletRequest
request
)
{
SecurityProperties
properties
=
SpringContextHolder
.
getBean
(
SecurityProperties
.
class
);
String
bearerToken
=
request
.
getHeader
(
properties
.
getHeader
());
if
(
StringUtils
.
hasText
(
bearerToken
)
&&
bearerToken
.
startsWith
(
properties
.
getTokenStartWith
()))
{
return
bearerToken
.
substring
(
7
);
}
return
null
;
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java
0 → 100644
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
import
io.jsonwebtoken.*
;
import
io.jsonwebtoken.io.Decoders
;
import
io.jsonwebtoken.security.Keys
;
import
lombok.extern.slf4j.Slf4j
;
import
me.zhengjie.modules.security.config.SecurityProperties
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
org.springframework.security.core.userdetails.User
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
java.security.Key
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.stream.Collectors
;
/**
* @author /
*/
@Slf4j
@Component
public
class
TokenProvider
implements
InitializingBean
{
private
final
SecurityProperties
properties
;
private
static
final
String
AUTHORITIES_KEY
=
"auth"
;
private
Key
key
;
public
TokenProvider
(
SecurityProperties
properties
)
{
this
.
properties
=
properties
;
}
@Override
public
void
afterPropertiesSet
()
{
byte
[]
keyBytes
=
Decoders
.
BASE64
.
decode
(
properties
.
getBase64Secret
());
this
.
key
=
Keys
.
hmacShaKeyFor
(
keyBytes
);
}
public
String
createToken
(
Authentication
authentication
)
{
String
authorities
=
authentication
.
getAuthorities
().
stream
()
.
map
(
GrantedAuthority:
:
getAuthority
)
.
collect
(
Collectors
.
joining
(
","
));
long
now
=
(
new
Date
()).
getTime
();
Date
validity
=
new
Date
(
now
+
properties
.
getTokenValidityInSeconds
());
return
Jwts
.
builder
()
.
setSubject
(
authentication
.
getName
())
.
claim
(
AUTHORITIES_KEY
,
authorities
)
.
signWith
(
key
,
SignatureAlgorithm
.
HS512
)
.
setExpiration
(
validity
)
.
compact
();
}
Authentication
getAuthentication
(
String
token
)
{
Claims
claims
=
Jwts
.
parser
()
.
setSigningKey
(
key
)
.
parseClaimsJws
(
token
)
.
getBody
();
Collection
<?
extends
GrantedAuthority
>
authorities
=
Arrays
.
stream
(
claims
.
get
(
AUTHORITIES_KEY
).
toString
().
split
(
","
))
.
map
(
SimpleGrantedAuthority:
:
new
)
.
collect
(
Collectors
.
toList
());
User
principal
=
new
User
(
claims
.
getSubject
(),
""
,
authorities
);
return
new
UsernamePasswordAuthenticationToken
(
principal
,
token
,
authorities
);
}
boolean
validateToken
(
String
authToken
)
{
try
{
Jwts
.
parser
().
setSigningKey
(
key
).
parseClaimsJws
(
authToken
);
return
true
;
}
catch
(
io
.
jsonwebtoken
.
security
.
SecurityException
|
MalformedJwtException
e
)
{
log
.
info
(
"Invalid JWT signature."
);
e
.
printStackTrace
();
}
catch
(
ExpiredJwtException
e
)
{
log
.
info
(
"Expired JWT token."
);
e
.
printStackTrace
();
}
catch
(
UnsupportedJwtException
e
)
{
log
.
info
(
"Unsupported JWT token."
);
e
.
printStackTrace
();
}
catch
(
IllegalArgumentException
e
)
{
log
.
info
(
"JWT token compact of handler are invalid."
);
e
.
printStackTrace
();
}
return
false
;
}
public
String
getToken
(
HttpServletRequest
request
){
final
String
requestHeader
=
request
.
getHeader
(
properties
.
getHeader
());
if
(
requestHeader
!=
null
&&
requestHeader
.
startsWith
(
properties
.
getTokenStartWith
()))
{
return
requestHeader
.
substring
(
7
);
}
return
null
;
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthUser.java
→
eladmin-system/src/main/java/me/zhengjie/modules/security/security/
vo/
AuthUser.java
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
package
me.zhengjie.modules.security.security
.vo
;
import
lombok.Getter
;
import
lombok.Setter
;
...
...
eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtUser.java
→
eladmin-system/src/main/java/me/zhengjie/modules/security/security/
vo/
JwtUser.java
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
package
me.zhengjie.modules.security.security
.vo
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
lombok.AllArgsConstructor
;
...
...
@@ -18,11 +18,14 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public
class
JwtUser
implements
UserDetails
{
@JsonIgnore
private
final
Long
id
;
private
final
String
username
;
private
final
String
nickName
;
private
final
String
sex
;
@JsonIgnore
private
final
String
password
;
...
...
eladmin-system/src/main/java/me/zhengjie/modules/security/security/OnlineUser.java
→
eladmin-system/src/main/java/me/zhengjie/modules/security/security/
vo/
OnlineUser.java
View file @
284c25a1
package
me.zhengjie.modules.security.security
;
package
me.zhengjie.modules.security.security
.vo
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
...
...
@@ -16,6 +16,8 @@ public class OnlineUser {
private
String
userName
;
private
String
nickName
;
private
String
job
;
private
String
browser
;
...
...
eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtPermissionServiceImpl.java
deleted
100644 → 0
View file @
175a2eb6
package
me.zhengjie.modules.security.service
;
import
me.zhengjie.modules.system.domain.Menu
;
import
me.zhengjie.modules.system.domain.Role
;
import
me.zhengjie.modules.system.repository.RoleRepository
;
import
me.zhengjie.modules.system.service.dto.UserDto
;
import
me.zhengjie.utils.StringUtils
;
import
org.springframework.cache.annotation.CacheConfig
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
org.springframework.stereotype.Service
;
import
java.util.Collection
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
/**
* @author Zheng Jie
*/
@Service
@CacheConfig
(
cacheNames
=
"role"
)
public
class
JwtPermissionServiceImpl
{
private
final
RoleRepository
roleRepository
;
public
JwtPermissionServiceImpl
(
RoleRepository
roleRepository
)
{
this
.
roleRepository
=
roleRepository
;
}
/**
* key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法
* @param user 用户信息
* @return Collection
*/
@Cacheable
(
key
=
"'loadPermissionByUser:' + #p0.username"
)
public
Collection
<
GrantedAuthority
>
mapToGrantedAuthorities
(
UserDto
user
)
{
System
.
out
.
println
(
"--------------------loadPermissionByUser:"
+
user
.
getUsername
()
+
"---------------------"
);
Set
<
Role
>
roles
=
roleRepository
.
findByUsers_Id
(
user
.
getId
());
Set
<
String
>
permissions
=
roles
.
stream
().
filter
(
role
->
StringUtils
.
isNotBlank
(
role
.
getPermission
())).
map
(
Role:
:
getPermission
).
collect
(
Collectors
.
toSet
());
permissions
.
addAll
(
roles
.
stream
().
flatMap
(
role
->
role
.
getMenus
().
stream
())
.
filter
(
menu
->
StringUtils
.
isNotBlank
(
menu
.
getPermission
()))
.
map
(
Menu:
:
getPermission
).
collect
(
Collectors
.
toSet
())
);
return
permissions
.
stream
().
map
(
permission
->
new
SimpleGrantedAuthority
(
permission
))
.
collect
(
Collectors
.
toList
());
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java
View file @
284c25a1
package
me.zhengjie.modules.security.service
;
import
me.zhengjie.modules.security.security.JwtUser
;
import
me.zhengjie.modules.security.security.OnlineUser
;
import
me.zhengjie.utils.EncryptUtils
;
import
me.zhengjie.utils.FileUtil
;
import
me.zhengjie.utils.PageUtil
;
import
me.zhengjie.utils.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.data.domain.Page
;
import
org.springframework.data.domain.PageImpl
;
import
me.zhengjie.modules.security.config.SecurityProperties
;
import
me.zhengjie.modules.security.security.vo.JwtUser
;
import
me.zhengjie.modules.security.security.vo.OnlineUser
;
import
me.zhengjie.utils.*
;
import
org.springframework.data.domain.Pageable
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
/**
* @author Zheng Jie
* @Date 2019年10月26日21:56:27
*/
@Service
@SuppressWarnings
({
"unchecked"
,
"all"
})
public
class
OnlineUserService
{
@Value
(
"${jwt.expiration}"
)
private
Long
expiration
;
private
final
SecurityProperties
properties
;
private
RedisUtils
redisUtils
;
@Value
(
"${jwt.online}"
)
private
String
onlineKey
;
private
final
RedisTemplate
redisTemplate
;
public
OnlineUserService
(
RedisTemplate
redisTemplate
)
{
this
.
redisTemplate
=
redisTemplate
;
public
OnlineUserService
(
SecurityProperties
properties
,
RedisUtils
redisUtils
)
{
this
.
properties
=
properties
;
this
.
redisUtils
=
redisUtils
;
}
/**
* 保存在线用户信息
* @param jwtUser /
* @param token /
* @param request /
*/
public
void
save
(
JwtUser
jwtUser
,
String
token
,
HttpServletRequest
request
){
String
job
=
jwtUser
.
getDept
()
+
"/"
+
jwtUser
.
getJob
();
String
ip
=
StringUtils
.
getIp
(
request
);
...
...
@@ -45,28 +39,38 @@ public class OnlineUserService {
String
address
=
StringUtils
.
getCityInfo
(
ip
);
OnlineUser
onlineUser
=
null
;
try
{
onlineUser
=
new
OnlineUser
(
jwtUser
.
getUsername
(),
job
,
browser
,
ip
,
address
,
EncryptUtils
.
desEncrypt
(
token
),
new
Date
());
onlineUser
=
new
OnlineUser
(
jwtUser
.
getUsername
(),
jwtUser
.
getNickName
(),
job
,
browser
,
ip
,
address
,
EncryptUtils
.
desEncrypt
(
token
),
new
Date
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
redisTemplate
.
opsForValue
().
set
(
onlineKey
+
token
,
onlineUser
);
redisTemplate
.
expire
(
onlineKey
+
token
,
expiration
,
TimeUnit
.
MILLISECONDS
);
redisUtils
.
set
(
properties
.
getOnlineKey
()
+
token
,
onlineUser
,
properties
.
getTokenValidityInSeconds
()/
1000
);
}
public
Page
<
OnlineUser
>
getAll
(
String
filter
,
Pageable
pageable
){
/**
* 查询全部数据
* @param filter /
* @param pageable /
* @return /
*/
public
Map
<
String
,
Object
>
getAll
(
String
filter
,
Pageable
pageable
){
List
<
OnlineUser
>
onlineUsers
=
getAll
(
filter
);
return
new
PageImpl
<
OnlineUser
>
(
return
PageUtil
.
toPage
(
PageUtil
.
toPage
(
pageable
.
getPageNumber
(),
pageable
.
getPageSize
(),
onlineUsers
),
pageable
,
onlineUsers
.
size
()
);
onlineUsers
.
size
()
);
}
/**
* 查询全部数据,不分页
* @param filter /
* @return /
*/
public
List
<
OnlineUser
>
getAll
(
String
filter
){
List
<
String
>
keys
=
new
ArrayList
<>(
redisTemplate
.
keys
(
o
nlineKey
+
"*"
)
)
;
List
<
String
>
keys
=
redisUtils
.
scan
(
properties
.
getO
nlineKey
()
+
"*"
);
Collections
.
reverse
(
keys
);
List
<
OnlineUser
>
onlineUsers
=
new
ArrayList
<>();
for
(
String
key
:
keys
)
{
OnlineUser
onlineUser
=
(
OnlineUser
)
redis
Template
.
opsForValue
()
.
get
(
key
);
OnlineUser
onlineUser
=
(
OnlineUser
)
redis
Utils
.
get
(
key
);
if
(
StringUtils
.
isNotBlank
(
filter
)){
if
(
onlineUser
.
toString
().
contains
(
filter
)){
onlineUsers
.
add
(
onlineUser
);
...
...
@@ -75,22 +79,35 @@ public class OnlineUserService {
onlineUsers
.
add
(
onlineUser
);
}
}
Collections
.
sort
(
onlineUsers
,
(
o1
,
o2
)
->
{
return
o2
.
getLoginTime
().
compareTo
(
o1
.
getLoginTime
());
});
onlineUsers
.
sort
((
o1
,
o2
)
->
o2
.
getLoginTime
().
compareTo
(
o1
.
getLoginTime
()));
return
onlineUsers
;
}
public
void
kickOut
(
String
val
)
throws
Exception
{
String
key
=
onlineKey
+
EncryptUtils
.
desDecrypt
(
val
);
redisTemplate
.
delete
(
key
);
/**
* 踢出用户
* @param key /
* @throws Exception /
*/
public
void
kickOut
(
String
key
)
throws
Exception
{
key
=
properties
.
getOnlineKey
()
+
EncryptUtils
.
desDecrypt
(
key
);
redisUtils
.
del
(
key
);
}
/**
* 退出登录
* @param token /
*/
public
void
logout
(
String
token
)
{
String
key
=
o
nlineKey
+
token
;
redis
Template
.
del
ete
(
key
);
String
key
=
properties
.
getO
nlineKey
()
+
token
;
redis
Utils
.
del
(
key
);
}
/**
* 导出
* @param all /
* @param response /
* @throws IOException /
*/
public
void
download
(
List
<
OnlineUser
>
all
,
HttpServletResponse
response
)
throws
IOException
{
List
<
Map
<
String
,
Object
>>
list
=
new
ArrayList
<>();
for
(
OnlineUser
user
:
all
)
{
...
...
@@ -105,4 +122,13 @@ public class OnlineUserService {
}
FileUtil
.
downloadExcel
(
list
,
response
);
}
/**
* 查询用户
* @param key /
* @return /
*/
public
OnlineUser
getOne
(
String
key
)
{
return
(
OnlineUser
)
redisUtils
.
get
(
key
);
}
}
eladmin-system/src/main/java/me/zhengjie/modules/security/service/
Jwt
UserDetailsServiceImpl.java
→
eladmin-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java
View file @
284c25a1
package
me.zhengjie.modules.security.service
;
import
me.zhengjie.exception.BadRequestException
;
import
me.zhengjie.modules.security.security.JwtUser
;
import
me.zhengjie.modules.security.security.vo.JwtUser
;
import
me.zhengjie.modules.system.service.RoleService
;
import
me.zhengjie.modules.system.service.UserService
;
import
me.zhengjie.modules.system.service.dto.*
;
import
org.springframework.security.core.userdetails.UserDetails
;
...
...
@@ -15,41 +16,45 @@ import java.util.Optional;
* @author Zheng Jie
* @date 2018-11-22
*/
@Service
@Service
(
"userDetailsService"
)
@Transactional
(
propagation
=
Propagation
.
SUPPORTS
,
readOnly
=
true
,
rollbackFor
=
Exception
.
class
)
public
class
Jwt
UserDetailsServiceImpl
implements
UserDetailsService
{
public
class
UserDetailsServiceImpl
implements
UserDetailsService
{
private
final
UserService
userService
;
private
final
JwtPermissionServiceImpl
permission
Service
;
private
final
RoleService
role
Service
;
public
Jwt
UserDetailsServiceImpl
(
UserService
userService
,
JwtPermissionServiceImpl
permission
Service
)
{
public
UserDetailsServiceImpl
(
UserService
userService
,
RoleService
role
Service
)
{
this
.
userService
=
userService
;
this
.
permissionService
=
permission
Service
;
this
.
roleService
=
role
Service
;
}
@Override
public
UserDetails
loadUserByUsername
(
String
username
){
UserDto
user
=
userService
.
findByName
(
username
);
if
(
user
==
null
)
{
throw
new
BadRequestException
(
"账号不存在"
);
}
else
{
if
(!
user
.
getEnabled
())
{
throw
new
BadRequestException
(
"账号未激活"
);
}
return
createJwtUser
(
user
);
}
}
p
ublic
UserDetails
createJwtUser
(
UserDto
user
)
{
p
rivate
UserDetails
createJwtUser
(
UserDto
user
)
{
return
new
JwtUser
(
user
.
getId
(),
user
.
getUsername
(),
user
.
getNickName
(),
user
.
getSex
(),
user
.
getPassword
(),
user
.
getAvatar
(),
user
.
getEmail
(),
user
.
getPhone
(),
Optional
.
ofNullable
(
user
.
getDept
()).
map
(
DeptSmallDto:
:
getName
).
orElse
(
null
),
Optional
.
ofNullable
(
user
.
getJob
()).
map
(
JobSmallDto:
:
getName
).
orElse
(
null
),
permission
Service
.
mapToGrantedAuthorities
(
user
),
role
Service
.
mapToGrantedAuthorities
(
user
),
user
.
getEnabled
(),
user
.
getCreateTime
(),
user
.
getLastPasswordResetTime
()
...
...
eladmin-system/src/main/java/me/zhengjie/modules/security/utils/JwtTokenUtil.java
deleted
100644 → 0
View file @
175a2eb6
package
me.zhengjie.modules.security.utils
;
import
io.jsonwebtoken.*
;
import
io.jsonwebtoken.impl.DefaultClock
;
import
me.zhengjie.modules.security.security.JwtUser
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.function.Function
;
/**
* @author /
*/
@Component
public
class
JwtTokenUtil
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
3301605591108950415L
;
private
Clock
clock
=
DefaultClock
.
INSTANCE
;
@Value
(
"${jwt.secret}"
)
private
String
secret
;
@Value
(
"${jwt.expiration}"
)
private
Long
expiration
;
@Value
(
"${jwt.header}"
)
private
String
tokenHeader
;
public
String
getUsernameFromToken
(
String
token
)
{
return
getClaimFromToken
(
token
,
Claims:
:
getSubject
);
}
private
Date
getIssuedAtDateFromToken
(
String
token
)
{
return
getClaimFromToken
(
token
,
Claims:
:
getIssuedAt
);
}
private
Date
getExpirationDateFromToken
(
String
token
)
{
return
getClaimFromToken
(
token
,
Claims:
:
getExpiration
);
}
private
<
T
>
T
getClaimFromToken
(
String
token
,
Function
<
Claims
,
T
>
claimsResolver
)
{
final
Claims
claims
=
getAllClaimsFromToken
(
token
);
return
claimsResolver
.
apply
(
claims
);
}
private
Claims
getAllClaimsFromToken
(
String
token
)
{
return
Jwts
.
parser
()
.
setSigningKey
(
secret
)
.
parseClaimsJws
(
token
)
.
getBody
();
}
private
Boolean
isTokenExpired
(
String
token
)
{
final
Date
expiration
=
getExpirationDateFromToken
(
token
);
return
expiration
.
before
(
clock
.
now
());
}
private
Boolean
isCreatedBeforeLastPasswordReset
(
Date
created
,
Date
lastPasswordReset
)
{
return
(
lastPasswordReset
!=
null
&&
created
.
before
(
lastPasswordReset
));
}
private
Boolean
ignoreTokenExpiration
(
String
token
)
{
// here you specify tokens, for that the expiration is ignored
return
false
;
}
public
String
generateToken
(
UserDetails
userDetails
)
{
Map
<
String
,
Object
>
claims
=
new
HashMap
<>(
16
);
return
doGenerateToken
(
claims
,
userDetails
.
getUsername
());
}
private
String
doGenerateToken
(
Map
<
String
,
Object
>
claims
,
String
subject
)
{
final
Date
createdDate
=
clock
.
now
();
final
Date
expirationDate
=
calculateExpirationDate
(
createdDate
);
return
Jwts
.
builder
()
.
setClaims
(
claims
)
.
setSubject
(
subject
)
.
setIssuedAt
(
createdDate
)
.
setExpiration
(
expirationDate
)
.
signWith
(
SignatureAlgorithm
.
HS512
,
secret
)
.
compact
();
}
public
Boolean
canTokenBeRefreshed
(
String
token
,
Date
lastPasswordReset
)
{
final
Date
created
=
getIssuedAtDateFromToken
(
token
);
return
!
isCreatedBeforeLastPasswordReset
(
created
,
lastPasswordReset
)
&&
(!
isTokenExpired
(
token
)
||
ignoreTokenExpiration
(
token
));
}
public
String
refreshToken
(
String
token
)
{
final
Date
createdDate
=
clock
.
now
();
final
Date
expirationDate
=
calculateExpirationDate
(
createdDate
);
final
Claims
claims
=
getAllClaimsFromToken
(
token
);
claims
.
setIssuedAt
(
createdDate
);
claims
.
setExpiration
(
expirationDate
);
return
Jwts
.
builder
()
.
setClaims
(
claims
)
.
signWith
(
SignatureAlgorithm
.
HS512
,
secret
)
.
compact
();
}
public
String
getToken
(
HttpServletRequest
request
){
final
String
requestHeader
=
request
.
getHeader
(
tokenHeader
);
String
startsWith
=
"Bearer "
;
if
(
requestHeader
!=
null
&&
requestHeader
.
startsWith
(
startsWith
))
{
return
requestHeader
.
substring
(
7
);
}
return
null
;
}
public
Boolean
validateToken
(
String
token
,
UserDetails
userDetails
)
{
JwtUser
user
=
(
JwtUser
)
userDetails
;
final
Date
created
=
getIssuedAtDateFromToken
(
token
);
// final Date expiration = getExpirationDateFromToken(token);
// 如果token存在,且token创建日期 > 最后修改密码的日期 则代表token有效
return
(!
isTokenExpired
(
token
)
&&
!
isCreatedBeforeLastPasswordReset
(
created
,
user
.
getLastPasswordResetDate
())
);
}
private
Date
calculateExpirationDate
(
Date
createdDate
)
{
return
new
Date
(
createdDate
.
getTime
()
+
expiration
);
}
}
eladmin-system/src/main/java/me/zhengjie/modules/system/domain/User.java
View file @
284c25a1
...
...
@@ -32,6 +32,13 @@ public class User implements Serializable {
@Column
(
unique
=
true
)
private
String
username
;
/** 用户昵称 */
@NotBlank
private
String
nickName
;
/** 性别 */
private
String
sex
;
@OneToOne
@JoinColumn
(
name
=
"avatar_id"
)
private
UserAvatar
userAvatar
;
...
...
eladmin-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java
View file @
284c25a1
...
...
@@ -5,6 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import
org.springframework.data.jpa.repository.JpaSpecificationExecutor
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author Zheng Jie
...
...
@@ -36,9 +37,9 @@ public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificat
/**
* 根据角色ID与菜单类型查询菜单
* @param
id
roleID
* @param
roleIds
roleID
s
* @param type 类型
* @return /
*/
LinkedHashSet
<
Menu
>
findByRoles_IdAndType
Is
Not
In
OrderBySortAsc
(
Long
id
,
I
nt
eger
type
);
LinkedHashSet
<
Menu
>
findByRoles_Id
In
AndTypeNotOrderBySortAsc
(
Set
<
Long
>
roleIds
,
i
nt
type
);
}
eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java
View file @
284c25a1
...
...
@@ -7,8 +7,10 @@ import me.zhengjie.aop.log.Log;
import
me.zhengjie.modules.system.domain.Role
;
import
me.zhengjie.exception.BadRequestException
;
import
me.zhengjie.modules.system.service.RoleService
;
import
me.zhengjie.modules.system.service.UserService
;
import
me.zhengjie.modules.system.service.dto.RoleQueryCriteria
;
import
me.zhengjie.modules.system.service.dto.RoleSmallDto
;
import
me.zhengjie.modules.system.service.dto.UserDto
;
import
me.zhengjie.utils.SecurityUtils
;
import
me.zhengjie.utils.ThrowableUtil
;
import
org.springframework.data.domain.Pageable
;
...
...
@@ -36,11 +38,13 @@ import java.util.stream.Collectors;
public
class
RoleController
{
private
final
RoleService
roleService
;
private
final
UserService
userService
;
private
static
final
String
ENTITY_NAME
=
"role"
;
public
RoleController
(
RoleService
roleService
)
{
public
RoleController
(
RoleService
roleService
,
UserService
userService
)
{
this
.
roleService
=
roleService
;
this
.
userService
=
userService
;
}
@ApiOperation
(
"获取单个role"
)
...
...
@@ -76,7 +80,8 @@ public class RoleController {
@ApiOperation
(
"获取用户级别"
)
@GetMapping
(
value
=
"/level"
)
public
ResponseEntity
getLevel
(){
List
<
Integer
>
levels
=
roleService
.
findByUsersId
(
SecurityUtils
.
getUserId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
());
UserDto
user
=
userService
.
findByName
(
SecurityUtils
.
getUsername
());
List
<
Integer
>
levels
=
roleService
.
findByUsersId
(
user
.
getId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
());
return
new
ResponseEntity
<>(
Dict
.
create
().
set
(
"level"
,
Collections
.
min
(
levels
)),
HttpStatus
.
OK
);
}
...
...
eladmin-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java
View file @
284c25a1
...
...
@@ -11,6 +11,7 @@ import me.zhengjie.modules.system.domain.vo.UserPassVo;
import
me.zhengjie.modules.system.service.DeptService
;
import
me.zhengjie.modules.system.service.RoleService
;
import
me.zhengjie.modules.system.service.dto.RoleSmallDto
;
import
me.zhengjie.modules.system.service.dto.UserDto
;
import
me.zhengjie.modules.system.service.dto.UserQueryCriteria
;
import
me.zhengjie.service.VerificationCodeService
;
import
me.zhengjie.utils.*
;
...
...
@@ -20,6 +21,8 @@ import org.springframework.http.HttpStatus;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.validation.annotation.Validated
;
...
...
@@ -39,17 +42,15 @@ import java.util.stream.Collectors;
@RequestMapping
(
"/api/users"
)
public
class
UserController
{
private
final
PasswordEncoder
passwordEncoder
;
private
final
UserService
userService
;
private
final
DataScope
dataScope
;
private
final
DeptService
deptService
;
private
final
RoleService
roleService
;
private
final
VerificationCodeService
verificationCodeService
;
public
UserController
(
UserService
userService
,
DataScope
dataScope
,
DeptService
deptService
,
RoleService
roleService
,
VerificationCodeService
verificationCodeService
)
{
public
UserController
(
PasswordEncoder
passwordEncoder
,
UserService
userService
,
DataScope
dataScope
,
DeptService
deptService
,
RoleService
roleService
,
VerificationCodeService
verificationCodeService
)
{
this
.
passwordEncoder
=
passwordEncoder
;
this
.
userService
=
userService
;
this
.
dataScope
=
dataScope
;
this
.
deptService
=
deptService
;
...
...
@@ -118,12 +119,25 @@ public class UserController {
return
new
ResponseEntity
(
HttpStatus
.
NO_CONTENT
);
}
@Log
(
"修改用户:个人中心"
)
@ApiOperation
(
"修改用户:个人中心"
)
@PutMapping
(
value
=
"center"
)
public
ResponseEntity
center
(
@Validated
(
User
.
Update
.
class
)
@RequestBody
User
resources
){
UserDto
userDto
=
userService
.
findByName
(
SecurityUtils
.
getUsername
());
if
(!
resources
.
getId
().
equals
(
userDto
.
getId
())){
throw
new
BadRequestException
(
"不能修改他人资料"
);
}
userService
.
updateCenter
(
resources
);
return
new
ResponseEntity
(
HttpStatus
.
NO_CONTENT
);
}
@Log
(
"删除用户"
)
@ApiOperation
(
"删除用户"
)
@DeleteMapping
(
value
=
"/{id}"
)
@PreAuthorize
(
"@el.check('user:del')"
)
public
ResponseEntity
delete
(
@PathVariable
Long
id
){
Integer
currentLevel
=
Collections
.
min
(
roleService
.
findByUsersId
(
SecurityUtils
.
getUserId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
()));
UserDto
user
=
userService
.
findByName
(
SecurityUtils
.
getUsername
());
Integer
currentLevel
=
Collections
.
min
(
roleService
.
findByUsersId
(
user
.
getId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
()));
Integer
optLevel
=
Collections
.
min
(
roleService
.
findByUsersId
(
id
).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
()));
if
(
currentLevel
>
optLevel
)
{
...
...
@@ -135,15 +149,15 @@ public class UserController {
@ApiOperation
(
"修改密码"
)
@PostMapping
(
value
=
"/updatePass"
)
public
ResponseEntity
updatePass
(
@RequestBody
UserPassVo
user
){
UserD
etails
userDetails
=
SecurityUtils
.
getUser
Details
(
);
if
(!
userDetails
.
getPassword
().
equals
(
EncryptUtils
.
encryptPassword
(
user
.
get
Old
Pass
(
)
))){
public
ResponseEntity
updatePass
(
@RequestBody
UserPassVo
passVo
){
UserD
to
user
=
userService
.
findByName
(
SecurityUtils
.
getUser
name
()
);
if
(!
passwordEncoder
.
matches
(
passVo
.
getOldPass
(),
user
.
getPass
word
())){
throw
new
BadRequestException
(
"修改失败,旧密码错误"
);
}
if
(
userDetails
.
getPassword
().
equals
(
EncryptUtils
.
encryptPassword
(
user
.
get
New
Pass
(
)
))){
if
(
passwordEncoder
.
matches
(
passVo
.
getNewPass
(),
user
.
getPass
word
())){
throw
new
BadRequestException
(
"新密码不能与旧密码相同"
);
}
userService
.
updatePass
(
user
Details
.
getUsername
(),
EncryptUtils
.
encryptPassword
(
user
.
getNewPass
()));
userService
.
updatePass
(
user
.
getUsername
(),
passwordEncoder
.
encode
(
passVo
.
getNewPass
()));
return
new
ResponseEntity
(
HttpStatus
.
OK
);
}
...
...
@@ -158,13 +172,13 @@ public class UserController {
@ApiOperation
(
"修改邮箱"
)
@PostMapping
(
value
=
"/updateEmail/{code}"
)
public
ResponseEntity
updateEmail
(
@PathVariable
String
code
,
@RequestBody
User
user
){
UserD
etails
userDetails
=
SecurityUtils
.
getUser
Details
(
);
if
(!
userDetails
.
getPassword
().
equals
(
EncryptUtils
.
encryp
tPassword
(
user
.
getPassword
()))
)
{
UserD
to
userDto
=
userService
.
findByName
(
SecurityUtils
.
getUser
name
()
);
if
(!
passwordEncoder
.
matches
(
user
.
ge
tPassword
(
),
user
Dto
.
getPassword
())){
throw
new
BadRequestException
(
"密码错误"
);
}
VerificationCode
verificationCode
=
new
VerificationCode
(
code
,
ElAdminConstant
.
RESET_MAIL
,
"email"
,
user
.
getEmail
());
verificationCodeService
.
validated
(
verificationCode
);
userService
.
updateEmail
(
userD
etails
.
getUsername
(),
user
.
getEmail
());
userService
.
updateEmail
(
userD
to
.
getUsername
(),
user
.
getEmail
());
return
new
ResponseEntity
(
HttpStatus
.
OK
);
}
...
...
@@ -173,7 +187,8 @@ public class UserController {
* @param resources /
*/
private
void
checkLevel
(
User
resources
)
{
Integer
currentLevel
=
Collections
.
min
(
roleService
.
findByUsersId
(
SecurityUtils
.
getUserId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
()));
UserDto
user
=
userService
.
findByName
(
SecurityUtils
.
getUsername
());
Integer
currentLevel
=
Collections
.
min
(
roleService
.
findByUsersId
(
user
.
getId
()).
stream
().
map
(
RoleSmallDto:
:
getLevel
).
collect
(
Collectors
.
toList
()));
Integer
optLevel
=
roleService
.
findByRoles
(
resources
.
getRoles
());
if
(
currentLevel
>
optLevel
)
{
throw
new
BadRequestException
(
"角色权限不足"
);
...
...
eladmin-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java
View file @
284c25a1
...
...
@@ -4,10 +4,14 @@ import me.zhengjie.modules.system.domain.Role;
import
me.zhengjie.modules.system.service.dto.RoleDto
;
import
me.zhengjie.modules.system.service.dto.RoleQueryCriteria
;
import
me.zhengjie.modules.system.service.dto.RoleSmallDto
;
import
me.zhengjie.modules.system.service.dto.UserDto
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.data.domain.Pageable
;
import
org.springframework.security.core.GrantedAuthority
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Set
;
...
...
@@ -99,4 +103,11 @@ public interface RoleService {
* @throws IOException /
*/
void
download
(
List
<
RoleDto
>
queryAll
,
HttpServletResponse
response
)
throws
IOException
;
/**
* 获取用户权限信息
* @param user 用户信息
* @return 权限信息
*/
Collection
<
GrantedAuthority
>
mapToGrantedAuthorities
(
UserDto
user
);
}
eladmin-system/src/main/java/me/zhengjie/modules/system/service/UserService.java
View file @
284c25a1
...
...
@@ -90,4 +90,10 @@ public interface UserService {
* @throws IOException /
*/
void
download
(
List
<
UserDto
>
queryAll
,
HttpServletResponse
response
)
throws
IOException
;
/**
* 用户自助修改资料
* @param resources /
*/
void
updateCenter
(
User
resources
);
}
eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDto.java
View file @
284c25a1
...
...
@@ -20,6 +20,10 @@ public class UserDto implements Serializable {
private
String
username
;
private
String
nickName
;
private
String
sex
;
private
String
avatar
;
private
String
email
;
...
...
Prev
1
2
3
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment