Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
SiEn
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hewei
SiEn
Commits
543097ed
Commit
543097ed
authored
Sep 25, 2020
by
hewei
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'double_realm_test' into 'master'
初步完成shiro See merge request hewei/Jumeirah!3
parents
19573744
0edcf9b6
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
1150 additions
and
244 deletions
+1150
-244
README.md
+14
-1
api-app/src/main/java/com/jumeirah/api/app/controller/AppHelloWorldController.java
+23
-5
api-app/src/main/java/com/jumeirah/api/app/controller/AppUserController.java
+13
-6
bootstrap/src/main/java/io/geekidea/springbootplus/config/ShiroConfig.java
+59
-21
bootstrap/src/main/java/io/geekidea/springbootplus/config/Swagger2Config.java
+75
-2
common/src/main/java/com/jumeirah/common/service/AppUserService.java
+3
-0
common/src/main/java/com/jumeirah/common/service/impl/AppUserServiceImpl.java
+112
-0
common/src/main/java/com/jumeirah/common/service/impl/SysLoginServiceImpl.java
+8
-10
config/src/main/java/io/geekidea/springbootplus/config/constant/AppLoginRedisKey.java
+61
-0
config/src/main/java/io/geekidea/springbootplus/config/constant/CommonConstant.java
+2
-2
config/src/main/java/io/geekidea/springbootplus/config/constant/CommonRedisKey.java
+1
-31
config/src/main/java/io/geekidea/springbootplus/config/constant/MerchantLoginRedisKey.java
+59
-0
config/src/main/java/io/geekidea/springbootplus/config/constant/SysLoginRedisKey.java
+59
-0
config/src/main/resources/config/application.yml
+3
-3
framework/src/main/java/io/geekidea/springbootplus/framework/log/aop/BaseLogAop.java
+1
-2
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/AppLoginRedisService.java
+1
-1
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/MerchantLoginRedisService.java
+98
-0
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/SysLoginRedisService.java
+98
-0
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/AppLoginRedisServiceImpl.java
+176
-0
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/MerchantLoginRedisServiceImpl.java
+175
-0
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/SysLoginRedisServiceImpl.java
+17
-17
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtFilter.java
+23
-8
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtRealmSystem.java
+0
-104
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtToken.java
+4
-1
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/realm/JwtRealmAppUser.java
+15
-7
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/realm/JwtRealmMerchant.java
+15
-6
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/realm/JwtRealmSystem.java
+15
-10
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/service/impl/ShiroLoginServiceImpl.java
+5
-5
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/util/JwtUtil.java
+7
-0
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/vo/JwtTokenRedisVo.java
+3
-0
framework/src/main/java/io/geekidea/springbootplus/framework/util/LoginUtil.java
+5
-2
No files found.
README.md
View file @
543097ed
...
@@ -69,11 +69,24 @@ api-system api-app api-merchant
...
@@ -69,11 +69,24 @@ api-system api-app api-merchant
注册业务逻辑要调用common模块中的service去操作
注册业务逻辑要调用common模块中的service去操作
## swagger文档
http://127.0.0.1:8889/api/doc.html#/home
左上角可以切换到不同的模块
## 权限验证
## 权限验证
使用shiro框架
Shiro 的核心:
Subject(主体): 用于记录当前的操作用户,Subject在shiro中是一个接口,接口中定义了很多认证授相关的方法,外部程序通过subject进行认证授权,而subject是通过SecurityManager安全管理器进行认证授权
SecurityManager(安全管理器):对Subject 进行管理,他是shiro的核心SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口。
Authenticator(认证器):对用户身份进行认证
Authorizer(授权器):用户通过认证后,来判断时候拥有该权限
realm:获取用户权限数据
sessionManager(会话管理):shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。
CacheManager(缓存管理器):将用户权限数据存储在缓存,这样可以提高性能。
authc:所有url都必须认证通过才可以访问;
authc:所有url都必须认证通过才可以访问;
...
...
api-app/src/main/java/com/jumeirah/api/app/controller/AppHelloWorldController.java
View file @
543097ed
...
@@ -6,6 +6,7 @@ import io.geekidea.springbootplus.framework.log.annotation.OperationLog;
...
@@ -6,6 +6,7 @@ import io.geekidea.springbootplus.framework.log.annotation.OperationLog;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.shiro.authz.annotation.RequiresRoles
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.RestController
;
...
@@ -31,7 +32,7 @@ public class AppHelloWorldController {
...
@@ -31,7 +32,7 @@ public class AppHelloWorldController {
*/
*/
@GetMapping
(
value
=
"/world"
)
@GetMapping
(
value
=
"/world"
)
@OperationLog
(
name
=
"helloWorld"
)
@OperationLog
(
name
=
"helloWorld"
)
@ApiOperation
(
value
=
"
Hello
World"
,
response
=
String
.
class
)
@ApiOperation
(
value
=
"
hello
World"
,
response
=
String
.
class
)
public
ApiResult
<
String
>
helloWorld
()
throws
IOException
{
public
ApiResult
<
String
>
helloWorld
()
throws
IOException
{
log
.
debug
(
"Hello World...app"
);
log
.
debug
(
"Hello World...app"
);
return
ApiResult
.
ok
(
"Hello World app"
);
return
ApiResult
.
ok
(
"Hello World app"
);
...
@@ -39,16 +40,33 @@ public class AppHelloWorldController {
...
@@ -39,16 +40,33 @@ public class AppHelloWorldController {
@GetMapping
(
value
=
"/needRole"
)
@GetMapping
(
value
=
"/needRole"
)
@OperationLog
(
name
=
"
helloWorld
"
)
@OperationLog
(
name
=
"
needRole
"
)
@ApiOperation
(
value
=
"
Hello World
"
,
response
=
String
.
class
)
@ApiOperation
(
value
=
"
needRole
"
,
response
=
String
.
class
)
public
ApiResult
<
String
>
needRole
()
throws
IOException
{
public
ApiResult
<
String
>
needRole
()
throws
IOException
{
log
.
debug
(
"Hello World...app"
);
log
.
debug
(
"Hello World...app"
);
return
ApiResult
.
ok
(
"Hello World app"
);
return
ApiResult
.
ok
(
"Hello World app"
);
}
}
@GetMapping
(
value
=
"/needRoleAdmin"
)
@OperationLog
(
name
=
"needRoleAdmin"
)
@ApiOperation
(
value
=
"needRoleAdmin"
,
response
=
String
.
class
)
@RequiresRoles
(
"app:admin"
)
public
ApiResult
<
String
>
needRoleAdmin
()
throws
IOException
{
log
.
debug
(
"Hello World...app"
);
return
ApiResult
.
ok
(
"Hello World needRoleAdmin"
);
}
@GetMapping
(
value
=
"/needRoleAll"
)
@OperationLog
(
name
=
"needRoleAll"
)
@ApiOperation
(
value
=
"needRoleAll"
,
response
=
String
.
class
)
@RequiresRoles
(
"app:all"
)
public
ApiResult
<
String
>
needRoleAll
()
throws
IOException
{
log
.
debug
(
"Hello World...app"
);
return
ApiResult
.
ok
(
"Hello World needRoleAll"
);
}
@GetMapping
(
value
=
"/noRole"
)
@GetMapping
(
value
=
"/noRole"
)
@OperationLog
(
name
=
"
helloWorld
"
)
@OperationLog
(
name
=
"
noRole
"
)
@ApiOperation
(
value
=
"
Hello World
"
,
response
=
String
.
class
)
@ApiOperation
(
value
=
"
noRole
"
,
response
=
String
.
class
)
public
ApiResult
<
String
>
noRole
()
throws
IOException
{
public
ApiResult
<
String
>
noRole
()
throws
IOException
{
log
.
debug
(
"Hello World...app"
);
log
.
debug
(
"Hello World...app"
);
return
ApiResult
.
ok
(
"Hello World app noRole"
);
return
ApiResult
.
ok
(
"Hello World app noRole"
);
...
...
api-app/src/main/java/com/jumeirah/api/app/controller/AppUserController.java
View file @
543097ed
...
@@ -2,6 +2,7 @@ package com.jumeirah.api.app.controller;
...
@@ -2,6 +2,7 @@ package com.jumeirah.api.app.controller;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.LoginParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.service.AppUserService
;
import
com.jumeirah.common.service.AppUserService
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
...
@@ -38,7 +39,7 @@ import javax.servlet.http.HttpServletResponse;
...
@@ -38,7 +39,7 @@ import javax.servlet.http.HttpServletResponse;
@Slf4j
@Slf4j
@RestController
@RestController
//@Module("api-app")
//@Module("api-app")
@Api
(
value
=
"用户API"
,
tags
=
{
"APP相关"
})
@Api
(
value
=
"用户API"
,
tags
=
{
"APP
用户
相关"
})
@RequestMapping
(
"/app/user/"
)
@RequestMapping
(
"/app/user/"
)
public
class
AppUserController
extends
BaseController
{
public
class
AppUserController
extends
BaseController
{
...
@@ -106,14 +107,20 @@ public class AppUserController extends BaseController {
...
@@ -106,14 +107,20 @@ public class AppUserController extends BaseController {
@ApiOperation
(
value
=
"注册"
,
notes
=
"web用户注册"
,
response
=
LoginSysUserTokenVo
.
class
)
@ApiOperation
(
value
=
"注册"
,
notes
=
"web用户注册"
,
response
=
LoginSysUserTokenVo
.
class
)
public
ApiResult
<
LoginSysUserTokenVo
>
register
(
@Validated
@RequestBody
RegisterParam
registerParam
,
HttpServletResponse
response
,
@RequestHeader
(
required
=
false
)
String
language
)
throws
Exception
{
public
ApiResult
<
LoginSysUserTokenVo
>
register
(
@Validated
@RequestBody
RegisterParam
registerParam
,
HttpServletResponse
response
,
@RequestHeader
(
required
=
false
)
String
language
)
throws
Exception
{
return
appUserService
.
register
(
registerParam
,
language
);
return
appUserService
.
register
(
registerParam
,
language
);
}
}
@PostMapping
(
"/
phoneL
ogin"
)
@PostMapping
(
"/
l
ogin"
)
@OperationLogIgnore
@OperationLogIgnore
@ApiOperation
(
value
=
"
手机号登陆"
,
notes
=
"手机号登陆
"
,
response
=
LoginSysUserTokenVo
.
class
)
@ApiOperation
(
value
=
"
登录"
,
notes
=
"系统用户登录
"
,
response
=
LoginSysUserTokenVo
.
class
)
public
ApiResult
<
LoginSysUserTokenVo
>
phoneLogin
(
@Validated
@RequestBody
RegisterParam
register
Param
,
HttpServletResponse
response
,
@RequestHeader
(
required
=
false
)
String
language
)
throws
Exception
{
public
ApiResult
<
LoginSysUserTokenVo
>
login
(
@Validated
@RequestBody
LoginParam
login
Param
,
HttpServletResponse
response
,
@RequestHeader
(
required
=
false
)
String
language
)
throws
Exception
{
return
appUserService
.
register
(
register
Param
,
language
);
return
appUserService
.
login
(
login
Param
,
language
);
}
}
// @PostMapping("/phoneLogin")
// @OperationLogIgnore
// @ApiOperation(value = "手机号登陆", notes = "手机号登陆", response = LoginSysUserTokenVo.class)
// public ApiResult<LoginSysUserTokenVo> phoneLogin(@Validated @RequestBody RegisterParam registerParam, HttpServletResponse response, @RequestHeader(required = false) String language) throws Exception {
// return appUserService.register(registerParam, language);
// }
}
}
bootstrap/src/main/java/io/geekidea/springbootplus/config/ShiroConfig.java
View file @
543097ed
...
@@ -20,11 +20,15 @@ import com.alibaba.fastjson.JSON;
...
@@ -20,11 +20,15 @@ import com.alibaba.fastjson.JSON;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.ShiroPermissionProperties
;
import
io.geekidea.springbootplus.config.properties.ShiroPermissionProperties
;
import
io.geekidea.springbootplus.config.properties.ShiroProperties
;
import
io.geekidea.springbootplus.config.properties.ShiroProperties
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.AppLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.MerchantLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.SysLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.exception.ShiroConfigException
;
import
io.geekidea.springbootplus.framework.shiro.exception.ShiroConfigException
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtCredentialsMatcher
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtCredentialsMatcher
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtFilter
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtFilter
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtRealm
;
import
io.geekidea.springbootplus.framework.shiro.jwt.realm.JwtRealmAppUser
;
import
io.geekidea.springbootplus.framework.shiro.jwt.realm.JwtRealmMerchant
;
import
io.geekidea.springbootplus.framework.shiro.jwt.realm.JwtRealmSystem
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.util.IniUtil
;
import
io.geekidea.springbootplus.framework.util.IniUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
...
@@ -41,6 +45,7 @@ import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
...
@@ -41,6 +45,7 @@ import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import
org.apache.shiro.mgt.DefaultSubjectDAO
;
import
org.apache.shiro.mgt.DefaultSubjectDAO
;
import
org.apache.shiro.mgt.SecurityManager
;
import
org.apache.shiro.mgt.SecurityManager
;
import
org.apache.shiro.mgt.SessionStorageEvaluator
;
import
org.apache.shiro.mgt.SessionStorageEvaluator
;
import
org.apache.shiro.realm.Realm
;
import
org.apache.shiro.spring.LifecycleBeanPostProcessor
;
import
org.apache.shiro.spring.LifecycleBeanPostProcessor
;
import
org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
;
import
org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
;
import
org.apache.shiro.spring.web.ShiroFilterFactoryBean
;
import
org.apache.shiro.spring.web.ShiroFilterFactoryBean
;
...
@@ -51,6 +56,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
...
@@ -51,6 +56,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import
org.springframework.boot.web.servlet.FilterRegistrationBean
;
import
org.springframework.boot.web.servlet.FilterRegistrationBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.web.filter.DelegatingFilterProxy
;
import
org.springframework.web.filter.DelegatingFilterProxy
;
import
javax.servlet.DispatcherType
;
import
javax.servlet.DispatcherType
;
...
@@ -103,13 +109,37 @@ public class ShiroConfig {
...
@@ -103,13 +109,37 @@ public class ShiroConfig {
}
}
/**
/**
*
JWT数据源验证
*
系统的用户及权限数据
*
*
* @return
* @return
*/
*/
@Bean
@Bean
public
JwtRealm
jwtRealm
(
LoginRedisService
loginRedisService
)
{
public
JwtRealmSystem
jwtRealmSystem
(
SysLoginRedisService
loginRedisService
)
{
JwtRealm
jwtRealm
=
new
JwtRealm
(
loginRedisService
);
JwtRealmSystem
jwtRealm
=
new
JwtRealmSystem
(
loginRedisService
);
jwtRealm
.
setCachingEnabled
(
false
);
jwtRealm
.
setCredentialsMatcher
(
credentialsMatcher
());
return
jwtRealm
;
}
/**
* app的用户及权限数据
*/
@Bean
public
JwtRealmAppUser
jwtRealmAppUser
(
AppLoginRedisService
appLoginRedisService
)
{
JwtRealmAppUser
jwtRealm
=
new
JwtRealmAppUser
(
appLoginRedisService
);
jwtRealm
.
setCachingEnabled
(
false
);
jwtRealm
.
setCredentialsMatcher
(
credentialsMatcher
());
return
jwtRealm
;
}
/**
* 商家的用户及权限数据
*/
@Bean
public
JwtRealmMerchant
jwtRealmMerchant
(
MerchantLoginRedisService
merchantLoginRedisService
)
{
JwtRealmMerchant
jwtRealm
=
new
JwtRealmMerchant
(
merchantLoginRedisService
);
jwtRealm
.
setCachingEnabled
(
false
);
jwtRealm
.
setCachingEnabled
(
false
);
jwtRealm
.
setCredentialsMatcher
(
credentialsMatcher
());
jwtRealm
.
setCredentialsMatcher
(
credentialsMatcher
());
return
jwtRealm
;
return
jwtRealm
;
...
@@ -118,8 +148,6 @@ public class ShiroConfig {
...
@@ -118,8 +148,6 @@ public class ShiroConfig {
/**
/**
* subject不存储到Session中
* subject不存储到Session中
*
* @return
*/
*/
@Bean
@Bean
public
SessionStorageEvaluator
sessionStorageEvaluator
()
{
public
SessionStorageEvaluator
sessionStorageEvaluator
()
{
...
@@ -142,14 +170,20 @@ public class ShiroConfig {
...
@@ -142,14 +170,20 @@ public class ShiroConfig {
/**
/**
* 安全管理器配置
* 安全管理器配置
*
* @return
*/
*/
@Bean
@Bean
public
SecurityManager
securityManager
(
LoginRedisService
l
oginRedisService
)
{
public
SecurityManager
securityManager
(
SysLoginRedisService
sysLoginRedisService
,
AppLoginRedisService
appLoginRedisService
,
MerchantLoginRedisService
merchantL
oginRedisService
)
{
DefaultWebSecurityManager
securityManager
=
new
DefaultWebSecurityManager
();
DefaultWebSecurityManager
securityManager
=
new
DefaultWebSecurityManager
();
// 设置多个realms
List
<
Realm
>
realms
=
new
ArrayList
<>();
realms
.
add
(
jwtRealmSystem
(
sysLoginRedisService
));
realms
.
add
(
jwtRealmAppUser
(
appLoginRedisService
));
realms
.
add
(
jwtRealmMerchant
(
merchantLoginRedisService
));
// 数据连接器
// 数据连接器
securityManager
.
setRealm
(
jwtRealm
(
loginRedisService
));
securityManager
.
setRealms
(
realms
);
// 设置session存储方式: 不使用sessionId保存
// 设置session存储方式: 不使用sessionId保存
securityManager
.
setSubjectDAO
(
subjectDAO
());
securityManager
.
setSubjectDAO
(
subjectDAO
());
SecurityUtils
.
setSecurityManager
(
securityManager
);
SecurityUtils
.
setSecurityManager
(
securityManager
);
...
@@ -160,7 +194,7 @@ public class ShiroConfig {
...
@@ -160,7 +194,7 @@ public class ShiroConfig {
* ShiroFilterFactoryBean过滤器配置
* ShiroFilterFactoryBean过滤器配置
*
*
* @param securityManager
* @param securityManager
* @param
l
oginRedisService
* @param
sysL
oginRedisService
* @param shiroProperties
* @param shiroProperties
* @param jwtProperties
* @param jwtProperties
* @return
* @return
...
@@ -168,15 +202,16 @@ public class ShiroConfig {
...
@@ -168,15 +202,16 @@ public class ShiroConfig {
@Bean
(
SHIRO_FILTER_NAME
)
@Bean
(
SHIRO_FILTER_NAME
)
public
ShiroFilterFactoryBean
shiroFilterFactoryBean
(
SecurityManager
securityManager
,
public
ShiroFilterFactoryBean
shiroFilterFactoryBean
(
SecurityManager
securityManager
,
ShiroLoginService
shiroLoginService
,
ShiroLoginService
shiroLoginService
,
LoginRedisService
l
oginRedisService
,
SysLoginRedisService
sysL
oginRedisService
,
ShiroProperties
shiroProperties
,
ShiroProperties
shiroProperties
,
JwtProperties
jwtProperties
)
{
JwtProperties
jwtProperties
,
RedisTemplate
redisTemplate
)
{
ShiroFilterFactoryBean
shiroFilterFactoryBean
=
new
ShiroFilterFactoryBean
();
ShiroFilterFactoryBean
shiroFilterFactoryBean
=
new
ShiroFilterFactoryBean
();
// 设置安全管理器
// 设置安全管理器
shiroFilterFactoryBean
.
setSecurityManager
(
securityManager
);
shiroFilterFactoryBean
.
setSecurityManager
(
securityManager
);
// 设置过滤器
// 设置过滤器
Map
<
String
,
Filter
>
filterMap
=
getFilterMap
(
shiroLoginService
,
loginRedisService
,
jwtProperties
);
Map
<
String
,
Filter
>
filterMap
=
getFilterMap
(
shiroLoginService
,
sysLoginRedisService
,
jwtProperties
,
redisTemplate
);
shiroFilterFactoryBean
.
setFilters
(
filterMap
);
shiroFilterFactoryBean
.
setFilters
(
filterMap
);
// 设置过滤器顺序
// 设置过滤器顺序
Map
<
String
,
String
>
filterChainMap
=
getFilterChainDefinitionMap
(
shiroProperties
);
Map
<
String
,
String
>
filterChainMap
=
getFilterChainDefinitionMap
(
shiroProperties
);
...
@@ -191,10 +226,11 @@ public class ShiroConfig {
...
@@ -191,10 +226,11 @@ public class ShiroConfig {
* @return
* @return
*/
*/
private
Map
<
String
,
Filter
>
getFilterMap
(
ShiroLoginService
shiroLoginService
,
private
Map
<
String
,
Filter
>
getFilterMap
(
ShiroLoginService
shiroLoginService
,
LoginRedisService
loginRedisService
,
SysLoginRedisService
loginRedisService
,
JwtProperties
jwtProperties
)
{
JwtProperties
jwtProperties
,
RedisTemplate
redisTemplate
)
{
Map
<
String
,
Filter
>
filterMap
=
new
LinkedHashMap
<>();
Map
<
String
,
Filter
>
filterMap
=
new
LinkedHashMap
<>();
filterMap
.
put
(
JWT_FILTER_NAME
,
new
JwtFilter
(
shiroLoginService
,
loginRedisService
,
jwtProperties
));
filterMap
.
put
(
JWT_FILTER_NAME
,
new
JwtFilter
(
shiroLoginService
,
loginRedisService
,
jwtProperties
,
redisTemplate
));
return
filterMap
;
return
filterMap
;
}
}
...
@@ -314,13 +350,15 @@ public class ShiroConfig {
...
@@ -314,13 +350,15 @@ public class ShiroConfig {
/**
/**
* 认证模式
* 认证模式
*
*
* @param
l
oginRedisService
* @param
sysL
oginRedisService
* @return
* @return
*/
*/
@Bean
@Bean
public
Authenticator
authenticator
(
LoginRedisService
l
oginRedisService
)
{
public
Authenticator
authenticator
(
SysLoginRedisService
sysL
oginRedisService
)
{
ModularRealmAuthenticator
authenticator
=
new
ModularRealmAuthenticator
();
ModularRealmAuthenticator
authenticator
=
new
ModularRealmAuthenticator
();
authenticator
.
setRealms
(
Arrays
.
asList
(
jwtRealm
(
loginRedisService
)));
List
<
Realm
>
realms
=
new
ArrayList
<>();
realms
.
add
(
jwtRealmSystem
(
sysLoginRedisService
));
authenticator
.
setRealms
(
realms
);
// 认证策略: 第一个成功
// 认证策略: 第一个成功
authenticator
.
setAuthenticationStrategy
(
new
FirstSuccessfulStrategy
());
authenticator
.
setAuthenticationStrategy
(
new
FirstSuccessfulStrategy
());
return
authenticator
;
return
authenticator
;
...
...
bootstrap/src/main/java/io/geekidea/springbootplus/config/Swagger2Config.java
View file @
543097ed
...
@@ -72,6 +72,7 @@ import static springfox.documentation.swagger.schema.ApiModelProperties.findApiM
...
@@ -72,6 +72,7 @@ import static springfox.documentation.swagger.schema.ApiModelProperties.findApiM
/**
/**
* Swagger2全局配置
* Swagger2全局配置
* 分组教程 https://sns.bladex.vip/q-342.html
*
*
* @author geekidea
* @author geekidea
* @date 2020/3/21
* @date 2020/3/21
...
@@ -128,12 +129,83 @@ public class Swagger2Config {
...
@@ -128,12 +129,83 @@ public class Swagger2Config {
return
Optional
.
fromNullable
(
input
.
declaringClass
());
return
Optional
.
fromNullable
(
input
.
declaringClass
());
}
}
// @Bean
// public Docket createRestApi() {
// // 获取需要扫描的包
// String[] basePackages = getBasePackages();
// ApiSelectorBuilder apiSelectorBuilder = new Docket(DocumentationType.SWAGGER_2)
// .apiInfo(apiInfo("默认", "1.0"))
// .select();
// // 如果扫描的包为空,则默认扫描类上有@Api注解的类
// if (ArrayUtils.isEmpty(basePackages)) {
// apiSelectorBuilder.apis(RequestHandlerSelectors.withClassAnnotation(Api.class));
// } else {
// // 扫描指定的包
// apiSelectorBuilder.apis(basePackage(basePackages));
// }
// Docket docket = apiSelectorBuilder.paths(PathSelectors.any())
// .build()
// .enable(swaggerProperties.isEnable())
// .ignoredParameterTypes(ignoredParameterTypes)
// .globalOperationParameters(getParameters());
// return docket;
// }
@Bean
public
Docket
restAppApi
()
{
// 获取需要扫描的包
String
[]
basePackages
=
{
"com.jumeirah.api.app.controller"
};
ApiSelectorBuilder
apiSelectorBuilder
=
new
Docket
(
DocumentationType
.
SWAGGER_2
)
.
apiInfo
(
apiInfo
())
.
groupName
(
"app"
)
.
select
();
// 如果扫描的包为空,则默认扫描类上有@Api注解的类
if
(
ArrayUtils
.
isEmpty
(
basePackages
))
{
apiSelectorBuilder
.
apis
(
RequestHandlerSelectors
.
withClassAnnotation
(
Api
.
class
));
}
else
{
// 扫描指定的包
apiSelectorBuilder
.
apis
(
basePackage
(
basePackages
));
}
Docket
docket
=
apiSelectorBuilder
.
paths
(
PathSelectors
.
any
())
.
build
()
.
enable
(
swaggerProperties
.
isEnable
())
.
ignoredParameterTypes
(
ignoredParameterTypes
)
.
globalOperationParameters
(
getParameters
());
return
docket
;
}
@Bean
@Bean
public
Docket
createRest
Api
()
{
public
Docket
restSys
Api
()
{
// 获取需要扫描的包
// 获取需要扫描的包
String
[]
basePackages
=
getBasePackages
()
;
String
[]
basePackages
=
{
"com.jumeirah.api.system.controlle"
}
;
ApiSelectorBuilder
apiSelectorBuilder
=
new
Docket
(
DocumentationType
.
SWAGGER_2
)
ApiSelectorBuilder
apiSelectorBuilder
=
new
Docket
(
DocumentationType
.
SWAGGER_2
)
.
apiInfo
(
apiInfo
())
.
apiInfo
(
apiInfo
())
.
groupName
(
"system"
)
.
select
();
// 如果扫描的包为空,则默认扫描类上有@Api注解的类
if
(
ArrayUtils
.
isEmpty
(
basePackages
))
{
apiSelectorBuilder
.
apis
(
RequestHandlerSelectors
.
withClassAnnotation
(
Api
.
class
));
}
else
{
// 扫描指定的包
apiSelectorBuilder
.
apis
(
basePackage
(
basePackages
));
}
Docket
docket
=
apiSelectorBuilder
.
paths
(
PathSelectors
.
any
())
.
build
()
.
enable
(
swaggerProperties
.
isEnable
())
.
ignoredParameterTypes
(
ignoredParameterTypes
)
.
globalOperationParameters
(
getParameters
());
return
docket
;
}
@Bean
public
Docket
restMerchantApi
()
{
// 获取需要扫描的包
String
[]
basePackages
=
{
"com.jumeirah.api.merchant.controller"
};
ApiSelectorBuilder
apiSelectorBuilder
=
new
Docket
(
DocumentationType
.
SWAGGER_2
)
.
apiInfo
(
apiInfo
())
.
groupName
(
"merchant"
)
.
select
();
.
select
();
// 如果扫描的包为空,则默认扫描类上有@Api注解的类
// 如果扫描的包为空,则默认扫描类上有@Api注解的类
if
(
ArrayUtils
.
isEmpty
(
basePackages
))
{
if
(
ArrayUtils
.
isEmpty
(
basePackages
))
{
...
@@ -150,6 +222,7 @@ public class Swagger2Config {
...
@@ -150,6 +222,7 @@ public class Swagger2Config {
return
docket
;
return
docket
;
}
}
/**
/**
* 获取apiInfo
* 获取apiInfo
*
*
...
...
common/src/main/java/com/jumeirah/common/service/AppUserService.java
View file @
543097ed
...
@@ -2,6 +2,7 @@ package com.jumeirah.common.service;
...
@@ -2,6 +2,7 @@ package com.jumeirah.common.service;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.LoginParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
...
@@ -18,6 +19,8 @@ import io.geekidea.springbootplus.framework.core.pagination.Paging;
...
@@ -18,6 +19,8 @@ import io.geekidea.springbootplus.framework.core.pagination.Paging;
public
interface
AppUserService
extends
BaseService
<
AppUser
>
{
public
interface
AppUserService
extends
BaseService
<
AppUser
>
{
ApiResult
<
LoginSysUserTokenVo
>
register
(
RegisterParam
registerParam
,
String
language
);
ApiResult
<
LoginSysUserTokenVo
>
register
(
RegisterParam
registerParam
,
String
language
);
ApiResult
<
LoginSysUserTokenVo
>
login
(
LoginParam
loginParam
,
String
language
);
ApiResult
<
LoginSysUserTokenVo
>
phoneLogin
(
RegisterParam
registerParam
,
String
language
);
ApiResult
<
LoginSysUserTokenVo
>
phoneLogin
(
RegisterParam
registerParam
,
String
language
);
...
...
common/src/main/java/com/jumeirah/common/service/impl/AppUserServiceImpl.java
View file @
543097ed
package
com
.
jumeirah
.
common
.
service
.
impl
;
package
com
.
jumeirah
.
common
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.core.metadata.OrderItem
;
import
com.baomidou.mybatisplus.core.metadata.OrderItem
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.entity.AppUser
;
import
com.jumeirah.common.enums.StateEnum
;
import
com.jumeirah.common.mapper.AppUserMapper
;
import
com.jumeirah.common.mapper.AppUserMapper
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.AppUserPageParam
;
import
com.jumeirah.common.param.LoginParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.param.RegisterParam
;
import
com.jumeirah.common.service.AppUserService
;
import
com.jumeirah.common.service.AppUserService
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
import
com.jumeirah.common.vo.AppUserQueryVo
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.SpringBootPlusProperties
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl
;
import
io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl
;
import
io.geekidea.springbootplus.framework.core.pagination.PageInfo
;
import
io.geekidea.springbootplus.framework.core.pagination.PageInfo
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
io.geekidea.springbootplus.framework.shiro.cache.AppLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.SaltUtil
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
import
io.geekidea.springbootplus.framework.util.PasswordUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.shiro.SecurityUtils
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.subject.Subject
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Lazy
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.time.Duration
;
import
java.util.concurrent.TimeUnit
;
/**
/**
* APP用户 服务实现类
* APP用户 服务实现类
*
*
...
@@ -30,6 +51,20 @@ import org.springframework.transaction.annotation.Transactional;
...
@@ -30,6 +51,20 @@ import org.springframework.transaction.annotation.Transactional;
public
class
AppUserServiceImpl
extends
BaseServiceImpl
<
AppUserMapper
,
AppUser
>
implements
AppUserService
{
public
class
AppUserServiceImpl
extends
BaseServiceImpl
<
AppUserMapper
,
AppUser
>
implements
AppUserService
{
@Autowired
@Autowired
private
RedisTemplate
redisTemplate
;
@Lazy
@Autowired
private
AppLoginRedisService
appLoginRedisService
;
@Lazy
@Autowired
private
JwtProperties
jwtProperties
;
@Autowired
private
SpringBootPlusProperties
springBootPlusProperties
;
@Autowired
private
AppUserMapper
appUserMapper
;
private
AppUserMapper
appUserMapper
;
@Override
@Override
...
@@ -38,6 +73,83 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserMapper, AppUser>
...
@@ -38,6 +73,83 @@ public class AppUserServiceImpl extends BaseServiceImpl<AppUserMapper, AppUser>
}
}
@Override
@Override
public
ApiResult
<
LoginSysUserTokenVo
>
login
(
LoginParam
loginParam
,
String
language
)
{
// 校验验证码
// checkVerifyCode(loginParam.getVerifyToken(), loginParam.getCode());
String
username
=
loginParam
.
getUsername
();
// 从数据库中获取登录用户信息
AppUser
appUser
=
appUserMapper
.
selectOne
(
new
QueryWrapper
<
AppUser
>(
new
AppUser
().
setUsername
(
username
)));
if
(
appUser
==
null
)
{
log
.
error
(
"登录失败,loginParam:{}"
,
loginParam
);
// throw new AuthenticationException("用户名或密码错误");
return
ApiResult
.
fail
(
ApiCode
.
PWD_OR_USERNAME_ERROR
,
language
);
}
if
(
StateEnum
.
DISABLE
.
getCode
().
equals
(
appUser
.
getState
()))
{
throw
new
AuthenticationException
(
"账号已禁用"
);
}
// 实际项目中,前端传过来的密码应先加密
// 原始密码明文:123456
// 原始密码前端加密:sha256(123456)
// 后台加密规则:sha256(sha256(123456) + salt)
String
encryptPassword
=
PasswordUtil
.
encrypt
(
loginParam
.
getPassword
(),
appUser
.
getSalt
());
if
(!
encryptPassword
.
equals
(
appUser
.
getPassword
()))
{
return
ApiResult
.
fail
(
ApiCode
.
PWD_OR_USERNAME_ERROR
,
language
);
}
// 将系统用户对象转换成登录用户对象
LoginSysUserVo
loginSysUserVo
=
new
LoginSysUserVo
();
loginSysUserVo
.
setUsername
(
username
);
// 获取数据库中保存的盐值
String
newSalt
=
SaltUtil
.
getSalt
(
appUser
.
getSalt
(),
jwtProperties
);
// 生成token字符串并返回
Long
expireSecond
=
jwtProperties
.
getExpireSecond
();
String
token
=
JwtUtil
.
generateToken
(
username
,
newSalt
,
Duration
.
ofSeconds
(
expireSecond
));
log
.
debug
(
"token:{}"
,
token
);
// 创建AuthenticationToken
JwtToken
jwtToken
=
JwtToken
.
build
(
token
,
username
,
newSalt
,
expireSecond
,
"app"
);
boolean
enableShiro
=
springBootPlusProperties
.
getShiro
().
isEnable
();
if
(
enableShiro
)
{
// 从SecurityUtils里边创建一个 subject
Subject
subject
=
SecurityUtils
.
getSubject
();
// 执行认证登录
subject
.
login
(
jwtToken
);
}
else
{
log
.
warn
(
"未启用Shiro"
);
}
// 缓存登录信息到Redis
appLoginRedisService
.
cacheLoginInfo
(
jwtToken
,
loginSysUserVo
);
log
.
debug
(
"登录成功,username:{}"
,
username
);
// 缓存登录信息到redis
String
tokenSha256
=
DigestUtils
.
sha256Hex
(
token
);
redisTemplate
.
opsForValue
().
set
(
tokenSha256
,
loginSysUserVo
,
1
,
TimeUnit
.
DAYS
);
// 返回token和登录用户信息对象
LoginSysUserTokenVo
loginSysUserTokenVo
=
new
LoginSysUserTokenVo
();
loginSysUserTokenVo
.
setToken
(
token
);
loginSysUserTokenVo
.
setLoginSysUserVo
(
loginSysUserVo
);
// 设置token响应头
// response.setHeader(JwtTokenUtil.getTokenName(), loginSysUserTokenVo.getToken());
return
ApiResult
.
ok
(
loginSysUserTokenVo
,
language
);
}
@Override
public
ApiResult
<
LoginSysUserTokenVo
>
phoneLogin
(
RegisterParam
registerParam
,
String
language
)
{
public
ApiResult
<
LoginSysUserTokenVo
>
phoneLogin
(
RegisterParam
registerParam
,
String
language
)
{
return
null
;
return
null
;
}
}
...
...
common/src/main/java/com/jumeirah/common/service/impl/SysLoginServiceImpl.java
View file @
543097ed
...
@@ -22,26 +22,26 @@ import com.jumeirah.common.entity.SysDepartment;
...
@@ -22,26 +22,26 @@ import com.jumeirah.common.entity.SysDepartment;
import
com.jumeirah.common.entity.SysRole
;
import
com.jumeirah.common.entity.SysRole
;
import
com.jumeirah.common.entity.SysUser
;
import
com.jumeirah.common.entity.SysUser
;
import
com.jumeirah.common.enums.StateEnum
;
import
com.jumeirah.common.enums.StateEnum
;
import
com.jumeirah.common.exception.VerificationCodeException
;
import
com.jumeirah.common.mapper.SysUserMapper
;
import
com.jumeirah.common.mapper.SysUserMapper
;
import
com.jumeirah.common.param.LoginParam
;
import
com.jumeirah.common.param.LoginParam
;
import
com.jumeirah.common.service.SysDepartmentService
;
import
com.jumeirah.common.service.SysLoginService
;
import
com.jumeirah.common.service.SysRolePermissionService
;
import
com.jumeirah.common.service.SysRoleService
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
import
com.jumeirah.common.vo.LoginSysUserTokenVo
;
import
io.geekidea.springbootplus.config.constant.CommonRedisKey
;
import
io.geekidea.springbootplus.config.constant.CommonRedisKey
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.SpringBootPlusProperties
;
import
io.geekidea.springbootplus.config.properties.SpringBootPlusProperties
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.
Sys
LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.SaltUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.SaltUtil
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
import
io.geekidea.springbootplus.framework.util.PasswordUtil
;
import
io.geekidea.springbootplus.framework.util.PasswordUtil
;
import
com.jumeirah.common.exception.VerificationCodeException
;
import
com.jumeirah.common.service.SysLoginService
;
import
com.jumeirah.common.service.SysDepartmentService
;
import
com.jumeirah.common.service.SysRolePermissionService
;
import
com.jumeirah.common.service.SysRoleService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.codec.digest.DigestUtils
;
...
@@ -61,8 +61,6 @@ import java.time.Duration;
...
@@ -61,8 +61,6 @@ import java.time.Duration;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
static
io
.
geekidea
.
springbootplus
.
framework
.
common
.
api
.
ApiResult
.
fail
;
/**
/**
* <p>
* <p>
* 登录服务实现类
* 登录服务实现类
...
@@ -78,7 +76,7 @@ public class SysLoginServiceImpl implements SysLoginService {
...
@@ -78,7 +76,7 @@ public class SysLoginServiceImpl implements SysLoginService {
@Lazy
@Lazy
@Autowired
@Autowired
private
LoginRedisService
loginRedisService
;
private
Sys
LoginRedisService
loginRedisService
;
@Lazy
@Lazy
@Autowired
@Autowired
...
@@ -180,7 +178,7 @@ public class SysLoginServiceImpl implements SysLoginService {
...
@@ -180,7 +178,7 @@ public class SysLoginServiceImpl implements SysLoginService {
log
.
debug
(
"token:{}"
,
token
);
log
.
debug
(
"token:{}"
,
token
);
// 创建AuthenticationToken
// 创建AuthenticationToken
JwtToken
jwtToken
=
JwtToken
.
build
(
token
,
username
,
newSalt
,
expireSecond
);
JwtToken
jwtToken
=
JwtToken
.
build
(
token
,
username
,
newSalt
,
expireSecond
,
"sys"
);
boolean
enableShiro
=
springBootPlusProperties
.
getShiro
().
isEnable
();
boolean
enableShiro
=
springBootPlusProperties
.
getShiro
().
isEnable
();
if
(
enableShiro
)
{
if
(
enableShiro
)
{
...
...
config/src/main/java/io/geekidea/springbootplus/config/constant/AppLoginRedisKey.java
0 → 100755
View file @
543097ed
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
config
.
constant
;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public
interface
AppLoginRedisKey
{
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String
LOGIN_TOKEN
=
"sys:login:token:%s"
;
/**
* 登录用户信息key
* login:user:username
*/
String
LOGIN_USER
=
"app:login:user:%s"
;
/**
* 登录用户盐值信息key
* login:salt:username
*/
// String LOGIN_SALT = "app:login:salt:%s";
String
LOGIN_SALT
=
"sys:login:salt:%s"
;
/**
* 登录用户username token
* login:user:token:username:token
*/
String
LOGIN_USER_TOKEN
=
"app:login:user:token:%s:%s"
;
/**
* 登录用户下的所有token
* login:user:token:username:*
*/
String
LOGIN_USER_ALL_TOKEN
=
"app:login:user:token:%s:*"
;
}
config/src/main/java/io/geekidea/springbootplus/config/constant/CommonConstant.java
View file @
543097ed
...
@@ -92,9 +92,9 @@ public interface CommonConstant {
...
@@ -92,9 +92,9 @@ public interface CommonConstant {
String
JWT_DEFAULT_SECRET
=
"666666"
;
String
JWT_DEFAULT_SECRET
=
"666666"
;
/**
/**
* JWT 默认过期时间,
3600L
,单位秒
* JWT 默认过期时间,
5184000L = 60天
,单位秒
*/
*/
Long
JWT_DEFAULT_EXPIRE_SECOND
=
36
00L
;
Long
JWT_DEFAULT_EXPIRE_SECOND
=
51840
00L
;
/**
/**
* 默认头像
* 默认头像
...
...
config/src/main/java/io/geekidea/springbootplus/config/constant/CommonRedisKey.java
View file @
543097ed
...
@@ -27,38 +27,8 @@ package io.geekidea.springbootplus.config.constant;
...
@@ -27,38 +27,8 @@ package io.geekidea.springbootplus.config.constant;
public
interface
CommonRedisKey
{
public
interface
CommonRedisKey
{
/**
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String
LOGIN_TOKEN
=
"login:token:%s"
;
/**
* 登录用户信息key
* login:user:username
*/
String
LOGIN_USER
=
"login:user:%s"
;
/**
* 登录用户盐值信息key
* login:salt:username
*/
String
LOGIN_SALT
=
"login:salt:%s"
;
/**
* 登录用户username token
* login:user:token:username:token
*/
String
LOGIN_USER_TOKEN
=
"login:user:token:%s:%s"
;
/**
* 登录用户下的所有token
* login:user:token:username:*
*/
String
LOGIN_USER_ALL_TOKEN
=
"login:user:token:%s:*"
;
/**
* 验证码
* 验证码
* verify.code:666666
* verify.code:666666
*/
*/
String
VERIFY_CODE
=
"verify.code:%s"
;
String
VERIFY_CODE
=
"verify.
sms
code:%s"
;
}
}
config/src/main/java/io/geekidea/springbootplus/config/constant/MerchantLoginRedisKey.java
0 → 100755
View file @
543097ed
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
config
.
constant
;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public
interface
MerchantLoginRedisKey
{
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String
LOGIN_TOKEN
=
"sys:login:token:%s"
;
/**
* 登录用户信息key
* login:user:username
*/
String
LOGIN_USER
=
"mer:login:user:%s"
;
/**
* 登录用户盐值信息key
* login:salt:username
*/
String
LOGIN_SALT
=
"sys:login:salt:%s"
;
/**
* 登录用户username token
* login:user:token:username:token
*/
String
LOGIN_USER_TOKEN
=
"mer:login:user:token:%s:%s"
;
/**
* 登录用户下的所有token
* login:user:token:username:*
*/
String
LOGIN_USER_ALL_TOKEN
=
"mer:login:user:token:%s:*"
;
}
config/src/main/java/io/geekidea/springbootplus/config/constant/SysLoginRedisKey.java
0 → 100755
View file @
543097ed
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
config
.
constant
;
/**
* <p>
* redis key 常量
* </p>
*
* @author geekidea
* @date 2019-05-23
**/
public
interface
SysLoginRedisKey
{
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
String
LOGIN_TOKEN
=
"sys:login:token:%s"
;
/**
* 登录用户信息key
* login:user:username
*/
String
LOGIN_USER
=
"sys:login:user:%s"
;
/**
* 登录用户盐值信息key
* login:salt:username
*/
String
LOGIN_SALT
=
"sys:login:salt:%s"
;
/**
* 登录用户username token
* login:user:token:username:token
*/
String
LOGIN_USER_TOKEN
=
"sys:login:user:token:%s:%s"
;
/**
* 登录用户下的所有token
* login:user:token:username:*
*/
String
LOGIN_USER_ALL_TOKEN
=
"sys:login:user:token:%s:*"
;
}
config/src/main/resources/config/application.yml
View file @
543097ed
...
@@ -7,7 +7,7 @@ server:
...
@@ -7,7 +7,7 @@ server:
context-path
:
/api
context-path
:
/api
tomcat
:
tomcat
:
max-threads
:
200
max-threads
:
200
min-spare-threads
:
10
min-spare-threads
:
5
uri-encoding
:
UTF-8
uri-encoding
:
UTF-8
############################# 访问路径、端口tomcat end ###############################
############################# 访问路径、端口tomcat end ###############################
...
@@ -183,7 +183,7 @@ spring-boot-plus:
...
@@ -183,7 +183,7 @@ spring-boot-plus:
# 权限配置
# 权限配置
anon
:
anon
:
# 排除登录 注册 登出
# 排除登录 注册 登出
-
/app/user/register,/app/user/phoneLogin,/sys/login,/sys/logout,/sys/register
-
/app/user/register,/app/user/phoneLogin,/
app/user/login,/
sys/login,/sys/logout,/sys/register
# 排除静态资源
# 排除静态资源
-
/static/**,/templates/**
-
/static/**,/templates/**
# 排除Swagger
# 排除Swagger
...
@@ -200,7 +200,7 @@ spring-boot-plus:
...
@@ -200,7 +200,7 @@ spring-boot-plus:
/upload/**=anon
/upload/**=anon
/verificationCode/**=anon
/verificationCode/**=anon
/enum=anon
/enum=anon
# /app/**=authc
/app/*=roles["app:all"]
######################## Spring Shiro end ##########################
######################## Spring Shiro end ##########################
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/log/aop/BaseLogAop.java
View file @
543097ed
...
@@ -45,7 +45,6 @@ import io.geekidea.springbootplus.framework.util.ClientInfoUtil;
...
@@ -45,7 +45,6 @@ import io.geekidea.springbootplus.framework.util.ClientInfoUtil;
import
io.geekidea.springbootplus.framework.util.DateUtil
;
import
io.geekidea.springbootplus.framework.util.DateUtil
;
import
io.geekidea.springbootplus.framework.util.IpUtil
;
import
io.geekidea.springbootplus.framework.util.IpUtil
;
import
io.geekidea.springbootplus.framework.util.Jackson
;
import
io.geekidea.springbootplus.framework.util.Jackson
;
import
io.geekidea.springbootplus.framework.util.LoginUtil
;
import
io.geekidea.springbootplus.framework.util.UUIDUtil
;
import
io.geekidea.springbootplus.framework.util.UUIDUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.codec.digest.DigestUtils
;
...
@@ -824,7 +823,7 @@ public abstract class BaseLogAop {
...
@@ -824,7 +823,7 @@ public abstract class BaseLogAop {
}
}
// 设置当前登录信息
// 设置当前登录信息
sysOperationLog
.
setUserId
(
LoginUtil
.
getUserId
()).
setUserName
(
LoginUtil
.
getUsername
());
//
sysOperationLog.setUserId(LoginUtil.getUserId()).setUserName(LoginUtil.getUsername());
// 设置异常信息
// 设置异常信息
if
(
exception
!=
null
)
{
if
(
exception
!=
null
)
{
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/LoginRedisService.java
→
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/
App
LoginRedisService.java
View file @
543097ed
...
@@ -28,7 +28,7 @@ import io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo;
...
@@ -28,7 +28,7 @@ import io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo;
* @date 2019-09-30
* @date 2019-09-30
* @since 1.3.0.RELEASE
* @since 1.3.0.RELEASE
**/
**/
public
interface
LoginRedisService
{
public
interface
App
LoginRedisService
{
/**
/**
* 缓存登录信息
* 缓存登录信息
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/MerchantLoginRedisService.java
0 → 100755
View file @
543097ed
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
/**
* 登录信息Redis缓存操作服务
*
* @author geekidea
* @date 2019-09-30
* @since 1.3.0.RELEASE
**/
public
interface
MerchantLoginRedisService
{
/**
* 缓存登录信息
*
* @param jwtToken
* @param loginSysUserVo
*/
void
cacheLoginInfo
(
JwtToken
jwtToken
,
LoginSysUserVo
loginSysUserVo
);
/**
* 刷新登录信息
*
* @param oldToken
* @param username
* @param newJwtToken
*/
void
refreshLoginInfo
(
String
oldToken
,
String
username
,
JwtToken
newJwtToken
);
/**
* 通过用户名,从缓存中获取登录用户LoginSysUserRedisVo
*
* @param username
* @return
*/
LoginSysUserRedisVo
getLoginSysUserRedisVo
(
String
username
);
/**
* 获取登录用户对象
*
* @param username
* @return
*/
LoginSysUserVo
getLoginSysUserVo
(
String
username
);
/**
* 通过用户名称获取盐值
*
* @param username
* @return
*/
String
getSalt
(
String
username
);
/**
* 删除对应用户的Redis缓存
*
* @param token
* @param username
*/
void
deleteLoginInfo
(
String
token
,
String
username
);
/**
* 判断token在redis中是否存在
*
* @param token
* @return
*/
boolean
exists
(
String
token
);
/**
* 删除用户所有登录缓存
*
* @param username
*/
void
deleteUserAllCache
(
String
username
);
}
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/SysLoginRedisService.java
0 → 100755
View file @
543097ed
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
/**
* 登录信息Redis缓存操作服务
*
* @author geekidea
* @date 2019-09-30
* @since 1.3.0.RELEASE
**/
public
interface
SysLoginRedisService
{
/**
* 缓存登录信息
*
* @param jwtToken
* @param loginSysUserVo
*/
void
cacheLoginInfo
(
JwtToken
jwtToken
,
LoginSysUserVo
loginSysUserVo
);
/**
* 刷新登录信息
*
* @param oldToken
* @param username
* @param newJwtToken
*/
void
refreshLoginInfo
(
String
oldToken
,
String
username
,
JwtToken
newJwtToken
);
/**
* 通过用户名,从缓存中获取登录用户LoginSysUserRedisVo
*
* @param username
* @return
*/
LoginSysUserRedisVo
getLoginSysUserRedisVo
(
String
username
);
/**
* 获取登录用户对象
*
* @param username
* @return
*/
LoginSysUserVo
getLoginSysUserVo
(
String
username
);
/**
* 通过用户名称获取盐值
*
* @param username
* @return
*/
String
getSalt
(
String
username
);
/**
* 删除对应用户的Redis缓存
*
* @param token
* @param username
*/
void
deleteLoginInfo
(
String
token
,
String
username
);
/**
* 判断token在redis中是否存在
*
* @param token
* @return
*/
boolean
exists
(
String
token
);
/**
* 删除用户所有登录缓存
*
* @param username
*/
void
deleteUserAllCache
(
String
username
);
}
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/AppLoginRedisServiceImpl.java
0 → 100644
View file @
543097ed
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
.
impl
;
import
io.geekidea.springbootplus.config.constant.AppLoginRedisKey
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.framework.common.bean.ClientInfo
;
import
io.geekidea.springbootplus.framework.shiro.cache.AppLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.convert.LoginSysUserVoConvert
;
import
io.geekidea.springbootplus.framework.shiro.convert.ShiroMapstructConvert
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.JwtTokenRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
import
io.geekidea.springbootplus.framework.util.ClientInfoUtil
;
import
io.geekidea.springbootplus.framework.util.HttpServletRequestUtil
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
java.time.Duration
;
import
java.util.List
;
import
java.util.Set
;
@Service
public
class
AppLoginRedisServiceImpl
implements
AppLoginRedisService
{
@Autowired
private
JwtProperties
jwtProperties
;
@Autowired
private
RedisTemplate
redisTemplate
;
/**
* key-value: 有过期时间-->token过期时间
* 1. tokenMd5:jwtTokenRedisVo
* 2. username:loginSysUserRedisVo
* 3. username:salt
* hash: 没有过期时间,统计在线的用户信息
* username:num
*/
@Override
public
void
cacheLoginInfo
(
JwtToken
jwtToken
,
LoginSysUserVo
loginSysUserVo
)
{
if
(
jwtToken
==
null
)
{
throw
new
IllegalArgumentException
(
"jwtToken不能为空"
);
}
if
(
loginSysUserVo
==
null
)
{
throw
new
IllegalArgumentException
(
"loginSysUserVo不能为空"
);
}
// token
String
token
=
jwtToken
.
getToken
();
// 盐值
String
salt
=
jwtToken
.
getSalt
();
// 登录用户名称
String
username
=
loginSysUserVo
.
getUsername
();
// token md5值
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
// Redis缓存JWT Token信息
JwtTokenRedisVo
jwtTokenRedisVo
=
ShiroMapstructConvert
.
INSTANCE
.
jwtTokenToJwtTokenRedisVo
(
jwtToken
);
// 用户客户端信息
ClientInfo
clientInfo
=
ClientInfoUtil
.
get
(
HttpServletRequestUtil
.
getRequest
());
// Redis缓存登录用户信息
// 将LoginSysUserVo对象复制到LoginSysUserRedisVo,使用mapstruct进行对象属性复制
LoginSysUserRedisVo
loginSysUserRedisVo
=
LoginSysUserVoConvert
.
INSTANCE
.
voToRedisVo
(
loginSysUserVo
);
loginSysUserRedisVo
.
setSalt
(
salt
);
loginSysUserRedisVo
.
setClientInfo
(
clientInfo
);
// Redis过期时间与JwtToken过期时间一致
Duration
expireDuration
=
Duration
.
ofSeconds
(
jwtToken
.
getExpireSecond
());
// 判断是否启用单个用户登录,如果是,这每个用户只有一个有效token
boolean
singleLogin
=
jwtProperties
.
isSingleLogin
();
if
(
singleLogin
)
{
deleteUserAllCache
(
username
);
}
// 1. tokenMd5:jwtTokenRedisVo
String
loginTokenRedisKey
=
String
.
format
(
AppLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
);
redisTemplate
.
opsForValue
().
set
(
loginTokenRedisKey
,
jwtTokenRedisVo
,
expireDuration
);
// 2. username:loginSysUserRedisVo
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER
,
username
),
loginSysUserRedisVo
,
expireDuration
);
// 3. salt hash,方便获取盐值鉴权
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_SALT
,
username
),
salt
,
expireDuration
);
// 4. login user token
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
),
loginTokenRedisKey
,
expireDuration
);
}
@Override
public
void
refreshLoginInfo
(
String
oldToken
,
String
username
,
JwtToken
newJwtToken
)
{
// 获取缓存的登录用户信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
getLoginSysUserRedisVo
(
username
);
// 删除之前的token信息
deleteLoginInfo
(
oldToken
,
username
);
// 缓存登录信息
cacheLoginInfo
(
newJwtToken
,
loginSysUserRedisVo
);
}
@Override
public
LoginSysUserRedisVo
getLoginSysUserRedisVo
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
return
(
LoginSysUserRedisVo
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER
,
username
));
}
@Override
public
LoginSysUserVo
getLoginSysUserVo
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
LoginSysUserRedisVo
userRedisVo
=
getLoginSysUserRedisVo
(
username
);
return
userRedisVo
;
}
@Override
public
String
getSalt
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
String
salt
=
(
String
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_SALT
,
username
));
return
salt
;
}
@Override
public
void
deleteLoginInfo
(
String
token
,
String
username
)
{
if
(
token
==
null
)
{
throw
new
IllegalArgumentException
(
"token不能为空"
);
}
if
(
username
==
null
)
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
// 1. delete tokenMd5
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
// 2. delete username
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER
,
username
));
// 3. delete salt
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_SALT
,
username
));
// 4. delete user token
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
));
}
@Override
public
boolean
exists
(
String
token
)
{
if
(
token
==
null
)
{
throw
new
IllegalArgumentException
(
"token不能为空"
);
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
Object
object
=
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
return
object
!=
null
;
}
@Override
public
void
deleteUserAllCache
(
String
username
)
{
Set
<
String
>
userTokenMd5Set
=
redisTemplate
.
keys
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER_ALL_TOKEN
,
username
));
if
(
CollectionUtils
.
isEmpty
(
userTokenMd5Set
))
{
return
;
}
// 1. 删除登录用户的所有token信息
List
<
String
>
tokenMd5List
=
redisTemplate
.
opsForValue
().
multiGet
(
userTokenMd5Set
);
redisTemplate
.
delete
(
tokenMd5List
);
// 2. 删除登录用户的所有user:token信息
redisTemplate
.
delete
(
userTokenMd5Set
);
// 3. 删除登录用户信息
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_USER
,
username
));
// 4. 删除登录用户盐值信息
redisTemplate
.
delete
(
String
.
format
(
AppLoginRedisKey
.
LOGIN_SALT
,
username
));
}
}
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/MerchantLoginRedisServiceImpl.java
0 → 100644
View file @
543097ed
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
.
impl
;
import
io.geekidea.springbootplus.config.constant.MerchantLoginRedisKey
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.framework.common.bean.ClientInfo
;
import
io.geekidea.springbootplus.framework.shiro.cache.MerchantLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.convert.LoginSysUserVoConvert
;
import
io.geekidea.springbootplus.framework.shiro.convert.ShiroMapstructConvert
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.JwtTokenRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserVo
;
import
io.geekidea.springbootplus.framework.util.ClientInfoUtil
;
import
io.geekidea.springbootplus.framework.util.HttpServletRequestUtil
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
java.time.Duration
;
import
java.util.List
;
import
java.util.Set
;
@Service
public
class
MerchantLoginRedisServiceImpl
implements
MerchantLoginRedisService
{
@Autowired
private
JwtProperties
jwtProperties
;
@Autowired
private
RedisTemplate
redisTemplate
;
/**
* key-value: 有过期时间-->token过期时间
* 1. tokenMd5:jwtTokenRedisVo
* 2. username:loginSysUserRedisVo
* 3. username:salt
* hash: 没有过期时间,统计在线的用户信息
* username:num
*/
@Override
public
void
cacheLoginInfo
(
JwtToken
jwtToken
,
LoginSysUserVo
loginSysUserVo
)
{
if
(
jwtToken
==
null
)
{
throw
new
IllegalArgumentException
(
"jwtToken不能为空"
);
}
if
(
loginSysUserVo
==
null
)
{
throw
new
IllegalArgumentException
(
"loginSysUserVo不能为空"
);
}
// token
String
token
=
jwtToken
.
getToken
();
// 盐值
String
salt
=
jwtToken
.
getSalt
();
// 登录用户名称
String
username
=
loginSysUserVo
.
getUsername
();
// token md5值
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
// Redis缓存JWT Token信息
JwtTokenRedisVo
jwtTokenRedisVo
=
ShiroMapstructConvert
.
INSTANCE
.
jwtTokenToJwtTokenRedisVo
(
jwtToken
);
// 用户客户端信息
ClientInfo
clientInfo
=
ClientInfoUtil
.
get
(
HttpServletRequestUtil
.
getRequest
());
// Redis缓存登录用户信息
// 将LoginSysUserVo对象复制到LoginSysUserRedisVo,使用mapstruct进行对象属性复制
LoginSysUserRedisVo
loginSysUserRedisVo
=
LoginSysUserVoConvert
.
INSTANCE
.
voToRedisVo
(
loginSysUserVo
);
loginSysUserRedisVo
.
setSalt
(
salt
);
loginSysUserRedisVo
.
setClientInfo
(
clientInfo
);
// Redis过期时间与JwtToken过期时间一致
Duration
expireDuration
=
Duration
.
ofSeconds
(
jwtToken
.
getExpireSecond
());
// 判断是否启用单个用户登录,如果是,这每个用户只有一个有效token
boolean
singleLogin
=
jwtProperties
.
isSingleLogin
();
if
(
singleLogin
)
{
deleteUserAllCache
(
username
);
}
// 1. tokenMd5:jwtTokenRedisVo
String
loginTokenRedisKey
=
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
);
redisTemplate
.
opsForValue
().
set
(
loginTokenRedisKey
,
jwtTokenRedisVo
,
expireDuration
);
// 2. username:loginSysUserRedisVo
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER
,
username
),
loginSysUserRedisVo
,
expireDuration
);
// 3. salt hash,方便获取盐值鉴权
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_SALT
,
username
),
salt
,
expireDuration
);
// 4. login user token
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
),
loginTokenRedisKey
,
expireDuration
);
}
@Override
public
void
refreshLoginInfo
(
String
oldToken
,
String
username
,
JwtToken
newJwtToken
)
{
// 获取缓存的登录用户信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
getLoginSysUserRedisVo
(
username
);
// 删除之前的token信息
deleteLoginInfo
(
oldToken
,
username
);
// 缓存登录信息
cacheLoginInfo
(
newJwtToken
,
loginSysUserRedisVo
);
}
@Override
public
LoginSysUserRedisVo
getLoginSysUserRedisVo
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
return
(
LoginSysUserRedisVo
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER
,
username
));
}
@Override
public
LoginSysUserVo
getLoginSysUserVo
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
LoginSysUserRedisVo
userRedisVo
=
getLoginSysUserRedisVo
(
username
);
return
userRedisVo
;
}
@Override
public
String
getSalt
(
String
username
)
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
String
salt
=
(
String
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_SALT
,
username
));
return
salt
;
}
@Override
public
void
deleteLoginInfo
(
String
token
,
String
username
)
{
if
(
token
==
null
)
{
throw
new
IllegalArgumentException
(
"token不能为空"
);
}
if
(
username
==
null
)
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
// 1. delete tokenMd5
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
// 2. delete username
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER
,
username
));
// 3. delete salt
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_SALT
,
username
));
// 4. delete user token
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
));
}
@Override
public
boolean
exists
(
String
token
)
{
if
(
token
==
null
)
{
throw
new
IllegalArgumentException
(
"token不能为空"
);
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
Object
object
=
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
return
object
!=
null
;
}
@Override
public
void
deleteUserAllCache
(
String
username
)
{
Set
<
String
>
userTokenMd5Set
=
redisTemplate
.
keys
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER_ALL_TOKEN
,
username
));
if
(
CollectionUtils
.
isEmpty
(
userTokenMd5Set
))
{
return
;
}
// 1. 删除登录用户的所有token信息
List
<
String
>
tokenMd5List
=
redisTemplate
.
opsForValue
().
multiGet
(
userTokenMd5Set
);
redisTemplate
.
delete
(
tokenMd5List
);
// 2. 删除登录用户的所有user:token信息
redisTemplate
.
delete
(
userTokenMd5Set
);
// 3. 删除登录用户信息
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_USER
,
username
));
// 4. 删除登录用户盐值信息
redisTemplate
.
delete
(
String
.
format
(
MerchantLoginRedisKey
.
LOGIN_SALT
,
username
));
}
}
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/LoginRedisServiceImpl.java
→
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/cache/impl/
Sys
LoginRedisServiceImpl.java
View file @
543097ed
...
@@ -16,10 +16,10 @@
...
@@ -16,10 +16,10 @@
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
.
impl
;
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
cache
.
impl
;
import
io.geekidea.springbootplus.config.constant.
Commo
nRedisKey
;
import
io.geekidea.springbootplus.config.constant.
SysLogi
nRedisKey
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.framework.common.bean.ClientInfo
;
import
io.geekidea.springbootplus.framework.common.bean.ClientInfo
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.
Sys
LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.convert.LoginSysUserVoConvert
;
import
io.geekidea.springbootplus.framework.shiro.convert.LoginSysUserVoConvert
;
import
io.geekidea.springbootplus.framework.shiro.convert.ShiroMapstructConvert
;
import
io.geekidea.springbootplus.framework.shiro.convert.ShiroMapstructConvert
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
...
@@ -47,7 +47,7 @@ import java.util.Set;
...
@@ -47,7 +47,7 @@ import java.util.Set;
* @since 1.3.0.RELEASE
* @since 1.3.0.RELEASE
**/
**/
@Service
@Service
public
class
LoginRedisServiceImpl
implements
LoginRedisService
{
public
class
SysLoginRedisServiceImpl
implements
Sys
LoginRedisService
{
@Autowired
@Autowired
private
JwtProperties
jwtProperties
;
private
JwtProperties
jwtProperties
;
...
@@ -102,14 +102,14 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -102,14 +102,14 @@ public class LoginRedisServiceImpl implements LoginRedisService {
}
}
// 1. tokenMd5:jwtTokenRedisVo
// 1. tokenMd5:jwtTokenRedisVo
String
loginTokenRedisKey
=
String
.
format
(
Commo
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
);
String
loginTokenRedisKey
=
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
);
redisTemplate
.
opsForValue
().
set
(
loginTokenRedisKey
,
jwtTokenRedisVo
,
expireDuration
);
redisTemplate
.
opsForValue
().
set
(
loginTokenRedisKey
,
jwtTokenRedisVo
,
expireDuration
);
// 2. username:loginSysUserRedisVo
// 2. username:loginSysUserRedisVo
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER
,
username
),
loginSysUserRedisVo
,
expireDuration
);
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER
,
username
),
loginSysUserRedisVo
,
expireDuration
);
// 3. salt hash,方便获取盐值鉴权
// 3. salt hash,方便获取盐值鉴权
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_SALT
,
username
),
salt
,
expireDuration
);
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_SALT
,
username
),
salt
,
expireDuration
);
// 4. login user token
// 4. login user token
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
),
loginTokenRedisKey
,
expireDuration
);
redisTemplate
.
opsForValue
().
set
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
),
loginTokenRedisKey
,
expireDuration
);
}
}
@Override
@Override
...
@@ -127,7 +127,7 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -127,7 +127,7 @@ public class LoginRedisServiceImpl implements LoginRedisService {
if
(
StringUtils
.
isBlank
(
username
))
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
}
return
(
LoginSysUserRedisVo
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER
,
username
));
return
(
LoginSysUserRedisVo
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER
,
username
));
}
}
@Override
@Override
...
@@ -144,7 +144,7 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -144,7 +144,7 @@ public class LoginRedisServiceImpl implements LoginRedisService {
if
(
StringUtils
.
isBlank
(
username
))
{
if
(
StringUtils
.
isBlank
(
username
))
{
throw
new
IllegalArgumentException
(
"username不能为空"
);
throw
new
IllegalArgumentException
(
"username不能为空"
);
}
}
String
salt
=
(
String
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_SALT
,
username
));
String
salt
=
(
String
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_SALT
,
username
));
return
salt
;
return
salt
;
}
}
...
@@ -158,13 +158,13 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -158,13 +158,13 @@ public class LoginRedisServiceImpl implements LoginRedisService {
}
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
// 1. delete tokenMd5
// 1. delete tokenMd5
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
// 2. delete username
// 2. delete username
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER
,
username
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER
,
username
));
// 3. delete salt
// 3. delete salt
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_SALT
,
username
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_SALT
,
username
));
// 4. delete user token
// 4. delete user token
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER_TOKEN
,
username
,
tokenMd5
));
}
}
@Override
@Override
...
@@ -173,13 +173,13 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -173,13 +173,13 @@ public class LoginRedisServiceImpl implements LoginRedisService {
throw
new
IllegalArgumentException
(
"token不能为空"
);
throw
new
IllegalArgumentException
(
"token不能为空"
);
}
}
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
Object
object
=
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
Object
object
=
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
return
object
!=
null
;
return
object
!=
null
;
}
}
@Override
@Override
public
void
deleteUserAllCache
(
String
username
)
{
public
void
deleteUserAllCache
(
String
username
)
{
Set
<
String
>
userTokenMd5Set
=
redisTemplate
.
keys
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER_ALL_TOKEN
,
username
));
Set
<
String
>
userTokenMd5Set
=
redisTemplate
.
keys
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER_ALL_TOKEN
,
username
));
if
(
CollectionUtils
.
isEmpty
(
userTokenMd5Set
))
{
if
(
CollectionUtils
.
isEmpty
(
userTokenMd5Set
))
{
return
;
return
;
}
}
...
@@ -190,9 +190,9 @@ public class LoginRedisServiceImpl implements LoginRedisService {
...
@@ -190,9 +190,9 @@ public class LoginRedisServiceImpl implements LoginRedisService {
// 2. 删除登录用户的所有user:token信息
// 2. 删除登录用户的所有user:token信息
redisTemplate
.
delete
(
userTokenMd5Set
);
redisTemplate
.
delete
(
userTokenMd5Set
);
// 3. 删除登录用户信息
// 3. 删除登录用户信息
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_USER
,
username
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_USER
,
username
));
// 4. 删除登录用户盐值信息
// 4. 删除登录用户盐值信息
redisTemplate
.
delete
(
String
.
format
(
Commo
nRedisKey
.
LOGIN_SALT
,
username
));
redisTemplate
.
delete
(
String
.
format
(
SysLogi
nRedisKey
.
LOGIN_SALT
,
username
));
}
}
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtFilter.java
View file @
543097ed
...
@@ -16,21 +16,25 @@
...
@@ -16,21 +16,25 @@
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
;
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
;
import
io.geekidea.springbootplus.config.constant.SysLoginRedisKey
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.
Sys
LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.vo.JwtTokenRedisVo
;
import
io.geekidea.springbootplus.framework.util.HttpServletResponseUtil
;
import
io.geekidea.springbootplus.framework.util.HttpServletResponseUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.authc.AuthenticationToken
;
import
org.apache.shiro.authc.AuthenticationToken
;
import
org.apache.shiro.subject.Subject
;
import
org.apache.shiro.subject.Subject
;
import
org.apache.shiro.web.filter.authc.AuthenticatingFilter
;
import
org.apache.shiro.web.filter.authc.AuthenticatingFilter
;
import
org.apache.shiro.web.util.WebUtils
;
import
org.apache.shiro.web.util.WebUtils
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.ServletResponse
;
...
@@ -47,16 +51,19 @@ import javax.servlet.http.HttpServletResponse;
...
@@ -47,16 +51,19 @@ import javax.servlet.http.HttpServletResponse;
@Slf4j
@Slf4j
public
class
JwtFilter
extends
AuthenticatingFilter
{
public
class
JwtFilter
extends
AuthenticatingFilter
{
private
RedisTemplate
redisTemplate
;
private
final
ShiroLoginService
shiroLoginService
;
private
final
ShiroLoginService
shiroLoginService
;
private
final
LoginRedisService
l
oginRedisService
;
private
final
SysLoginRedisService
sysL
oginRedisService
;
private
final
JwtProperties
jwtProperties
;
private
final
JwtProperties
jwtProperties
;
public
JwtFilter
(
ShiroLoginService
shiroLoginService
,
LoginRedisService
loginRedisService
,
JwtProperties
jwtProperties
)
{
public
JwtFilter
(
ShiroLoginService
shiroLoginService
,
SysLoginRedisService
loginRedisService
,
JwtProperties
jwtProperties
,
RedisTemplate
redisTemplate
)
{
this
.
shiroLoginService
=
shiroLoginService
;
this
.
shiroLoginService
=
shiroLoginService
;
this
.
l
oginRedisService
=
loginRedisService
;
this
.
sysL
oginRedisService
=
loginRedisService
;
this
.
jwtProperties
=
jwtProperties
;
this
.
jwtProperties
=
jwtProperties
;
this
.
redisTemplate
=
redisTemplate
;
}
}
/**
/**
...
@@ -77,22 +84,29 @@ public class JwtFilter extends AuthenticatingFilter {
...
@@ -77,22 +84,29 @@ public class JwtFilter extends AuthenticatingFilter {
throw
new
AuthenticationException
(
"JWT Token已过期,token:"
+
token
);
throw
new
AuthenticationException
(
"JWT Token已过期,token:"
+
token
);
}
}
Object
jwtTokenRedisVo
=
null
;
// 如果开启redis二次校验,或者设置为单个用户token登录,则先在redis中判断token是否存在
// 如果开启redis二次校验,或者设置为单个用户token登录,则先在redis中判断token是否存在
if
(
jwtProperties
.
isRedisCheck
()
||
jwtProperties
.
isSingleLogin
())
{
if
(
jwtProperties
.
isRedisCheck
()
||
jwtProperties
.
isSingleLogin
())
{
boolean
redisExpired
=
loginRedisService
.
exists
(
token
);
String
tokenMd5
=
DigestUtils
.
md5Hex
(
token
);
if
(!
redisExpired
)
{
jwtTokenRedisVo
=
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
SysLoginRedisKey
.
LOGIN_TOKEN
,
tokenMd5
));
// boolean redisExpired = sysLoginRedisService.exists(token);
if
(
jwtTokenRedisVo
==
null
)
{
throw
new
AuthenticationException
(
"Redis Token不存在,token:"
+
token
);
throw
new
AuthenticationException
(
"Redis Token不存在,token:"
+
token
);
}
}
}
}
String
username
=
JwtUtil
.
getUsername
(
token
);
String
username
=
JwtUtil
.
getUsername
(
token
);
String
salt
;
String
salt
;
if
(
jwtProperties
.
isSaltCheck
())
{
if
(
jwtProperties
.
isSaltCheck
())
{
salt
=
l
oginRedisService
.
getSalt
(
username
);
salt
=
sysL
oginRedisService
.
getSalt
(
username
);
}
else
{
}
else
{
salt
=
jwtProperties
.
getSecret
();
salt
=
jwtProperties
.
getSecret
();
}
}
return
JwtToken
.
build
(
token
,
username
,
salt
,
jwtProperties
.
getExpireSecond
());
JwtTokenRedisVo
jwt
=
(
JwtTokenRedisVo
)
jwtTokenRedisVo
;
return
JwtToken
.
build
(
token
,
username
,
salt
,
jwtProperties
.
getExpireSecond
(),
jwt
.
getType
());
}
}
/**
/**
...
@@ -118,6 +132,7 @@ public class JwtFilter extends AuthenticatingFilter {
...
@@ -118,6 +132,7 @@ public class JwtFilter extends AuthenticatingFilter {
}
}
/**
/**
* 执行登陆认证
* 判断是否允许访问
* 判断是否允许访问
*
*
* @param request
* @param request
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtRealmSystem.java
deleted
100755 → 0
View file @
19573744
/*
* Copyright 2019-2029 geekidea(https://github.com/geekidea)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.SetUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.shiro.authc.AuthenticationException
;
import
org.apache.shiro.authc.AuthenticationInfo
;
import
org.apache.shiro.authc.AuthenticationToken
;
import
org.apache.shiro.authc.SimpleAuthenticationInfo
;
import
org.apache.shiro.authz.AuthorizationInfo
;
import
org.apache.shiro.authz.SimpleAuthorizationInfo
;
import
org.apache.shiro.realm.AuthorizingRealm
;
import
org.apache.shiro.subject.PrincipalCollection
;
/**
* Shiro 授权认证-系统
*
* @author geekidea
* @date 2019-09-27
* @since 1.3.0.RELEASE
**/
@Slf4j
public
class
JwtRealmSystem
extends
AuthorizingRealm
{
private
LoginRedisService
loginRedisService
;
public
JwtRealmSystem
(
LoginRedisService
loginRedisService
)
{
this
.
loginRedisService
=
loginRedisService
;
}
@Override
public
boolean
supports
(
AuthenticationToken
token
)
{
return
token
!=
null
&&
token
instanceof
JwtToken
;
}
/**
* 授权认证,设置角色/权限信息
*
* @param principalCollection
* @return
*/
@Override
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principalCollection
)
{
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
// 设置角色/权限信息
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
// 获取username
String
username
=
jwtToken
.
getUsername
();
// 获取登录用户角色权限信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
loginRedisService
.
getLoginSysUserRedisVo
(
username
);
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
// 设置角色
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
loginSysUserRedisVo
.
getRoleCode
()));
// 设置权限
authorizationInfo
.
setStringPermissions
(
loginSysUserRedisVo
.
getPermissionCodes
());
return
authorizationInfo
;
}
/**
* 登录认证
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected
AuthenticationInfo
doGetAuthenticationInfo
(
AuthenticationToken
authenticationToken
)
throws
AuthenticationException
{
log
.
debug
(
"doGetAuthenticationInfo authenticationToken..."
);
// 校验token
JwtToken
jwtToken
=
(
JwtToken
)
authenticationToken
;
if
(
jwtToken
==
null
)
{
throw
new
AuthenticationException
(
"jwtToken不能为空"
);
}
String
salt
=
jwtToken
.
getSalt
();
if
(
StringUtils
.
isBlank
(
salt
))
{
throw
new
AuthenticationException
(
"salt不能为空"
);
}
return
new
SimpleAuthenticationInfo
(
jwtToken
,
salt
,
getName
()
);
}
}
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtToken.java
View file @
543097ed
...
@@ -37,6 +37,8 @@ import java.util.Date;
...
@@ -37,6 +37,8 @@ import java.util.Date;
public
class
JwtToken
implements
HostAuthenticationToken
{
public
class
JwtToken
implements
HostAuthenticationToken
{
private
static
final
long
serialVersionUID
=
5101247566043093405L
;
private
static
final
long
serialVersionUID
=
5101247566043093405L
;
private
String
type
;
/**
/**
* 登录ip
* 登录ip
*/
*/
...
@@ -70,7 +72,7 @@ public class JwtToken implements HostAuthenticationToken {
...
@@ -70,7 +72,7 @@ public class JwtToken implements HostAuthenticationToken {
private
String
credentials
;
private
String
credentials
;
public
static
JwtToken
build
(
String
token
,
String
username
,
String
salt
,
long
expireSecond
)
{
public
static
JwtToken
build
(
String
token
,
String
username
,
String
salt
,
long
expireSecond
,
String
type
)
{
DecodedJWT
decodedJwt
=
JwtUtil
.
getJwtInfo
(
token
);
DecodedJWT
decodedJwt
=
JwtUtil
.
getJwtInfo
(
token
);
Date
createDate
=
decodedJwt
.
getIssuedAt
();
Date
createDate
=
decodedJwt
.
getIssuedAt
();
Date
expireDate
=
decodedJwt
.
getExpiresAt
();
Date
expireDate
=
decodedJwt
.
getExpiresAt
();
...
@@ -79,6 +81,7 @@ public class JwtToken implements HostAuthenticationToken {
...
@@ -79,6 +81,7 @@ public class JwtToken implements HostAuthenticationToken {
.
setToken
(
token
)
.
setToken
(
token
)
.
setHost
(
IpUtil
.
getRequestIp
())
.
setHost
(
IpUtil
.
getRequestIp
())
.
setSalt
(
salt
)
.
setSalt
(
salt
)
.
setType
(
type
)
.
setCreateDate
(
createDate
)
.
setCreateDate
(
createDate
)
.
setExpireSecond
(
expireSecond
)
.
setExpireSecond
(
expireSecond
)
.
setExpireDate
(
expireDate
);
.
setExpireDate
(
expireDate
);
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/realm/JwtRealmAppUser.java
View file @
543097ed
...
@@ -16,9 +16,8 @@
...
@@ -16,9 +16,8 @@
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
.
realm
;
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
.
realm
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.
App
LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.SetUtils
;
import
org.apache.commons.collections4.SetUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
...
@@ -41,10 +40,10 @@ import org.apache.shiro.subject.PrincipalCollection;
...
@@ -41,10 +40,10 @@ import org.apache.shiro.subject.PrincipalCollection;
@Slf4j
@Slf4j
public
class
JwtRealmAppUser
extends
AuthorizingRealm
{
public
class
JwtRealmAppUser
extends
AuthorizingRealm
{
private
LoginRedisService
l
oginRedisService
;
private
AppLoginRedisService
appL
oginRedisService
;
public
JwtRealmAppUser
(
LoginRedisService
l
oginRedisService
)
{
public
JwtRealmAppUser
(
AppLoginRedisService
appL
oginRedisService
)
{
this
.
loginRedisService
=
l
oginRedisService
;
this
.
appLoginRedisService
=
appL
oginRedisService
;
}
}
@Override
@Override
...
@@ -63,15 +62,24 @@ public class JwtRealmAppUser extends AuthorizingRealm {
...
@@ -63,15 +62,24 @@ public class JwtRealmAppUser extends AuthorizingRealm {
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
// 设置角色/权限信息
// 设置角色/权限信息
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
if
(!
jwtToken
.
getType
().
equals
(
"app"
))
{
return
null
;
}
/*
// 获取username
// 获取username
String username = jwtToken.getUsername();
String username = jwtToken.getUsername();
// 获取登录用户角色权限信息
// 获取登录用户角色权限信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
l
oginRedisService
.
getLoginSysUserRedisVo
(
username
);
LoginSysUserRedisVo loginSysUserRedisVo =
appL
oginRedisService.getLoginSysUserRedisVo(username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 设置角色
// 设置角色
authorizationInfo.setRoles(SetUtils.hashSet(loginSysUserRedisVo.getRoleCode()));
authorizationInfo.setRoles(SetUtils.hashSet(loginSysUserRedisVo.getRoleCode()));
// 设置权限
// 设置权限
authorizationInfo
.
setStringPermissions
(
loginSysUserRedisVo
.
getPermissionCodes
());
authorizationInfo.setStringPermissions(loginSysUserRedisVo.getPermissionCodes());*/
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
// 设置角色
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
"app:all"
));
return
authorizationInfo
;
return
authorizationInfo
;
}
}
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/JwtRealmMerchant.java
→
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/
realm/
JwtRealmMerchant.java
View file @
543097ed
...
@@ -14,9 +14,10 @@
...
@@ -14,9 +14,10 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
;
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
.
realm
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.MerchantLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.SetUtils
;
import
org.apache.commons.collections4.SetUtils
;
...
@@ -40,10 +41,10 @@ import org.apache.shiro.subject.PrincipalCollection;
...
@@ -40,10 +41,10 @@ import org.apache.shiro.subject.PrincipalCollection;
@Slf4j
@Slf4j
public
class
JwtRealmMerchant
extends
AuthorizingRealm
{
public
class
JwtRealmMerchant
extends
AuthorizingRealm
{
private
LoginRedisService
l
oginRedisService
;
private
MerchantLoginRedisService
merchantL
oginRedisService
;
public
JwtRealmMerchant
(
LoginRedisService
l
oginRedisService
)
{
public
JwtRealmMerchant
(
MerchantLoginRedisService
merchantL
oginRedisService
)
{
this
.
loginRedisService
=
l
oginRedisService
;
this
.
merchantLoginRedisService
=
merchantL
oginRedisService
;
}
}
@Override
@Override
...
@@ -59,19 +60,27 @@ public class JwtRealmMerchant extends AuthorizingRealm {
...
@@ -59,19 +60,27 @@ public class JwtRealmMerchant extends AuthorizingRealm {
*/
*/
@Override
@Override
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principalCollection
)
{
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principalCollection
)
{
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
// 设置角色/权限信息
// 设置角色/权限信息
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
if
(!
jwtToken
.
getType
().
equals
(
"mer"
))
{
return
null
;
}
// 获取username
// 获取username
String
username
=
jwtToken
.
getUsername
();
String
username
=
jwtToken
.
getUsername
();
// 获取登录用户角色权限信息
// 获取登录用户角色权限信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
l
oginRedisService
.
getLoginSysUserRedisVo
(
username
);
LoginSysUserRedisVo
loginSysUserRedisVo
=
merchantL
oginRedisService
.
getLoginSysUserRedisVo
(
username
);
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
// 设置角色
// 设置角色
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
loginSysUserRedisVo
.
getRoleCode
()));
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
loginSysUserRedisVo
.
getRoleCode
()));
// 设置权限
// 设置权限
authorizationInfo
.
setStringPermissions
(
loginSysUserRedisVo
.
getPermissionCodes
());
authorizationInfo
.
setStringPermissions
(
loginSysUserRedisVo
.
getPermissionCodes
());
return
authorizationInfo
;
return
authorizationInfo
;
}
}
/**
/**
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/
JwtReal
m.java
→
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/jwt/
realm/JwtRealmSyste
m.java
View file @
543097ed
...
@@ -14,9 +14,10 @@
...
@@ -14,9 +14,10 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
;
package
io
.
geekidea
.
springbootplus
.
framework
.
shiro
.
jwt
.
realm
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.SysLoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.SetUtils
;
import
org.apache.commons.collections4.SetUtils
;
...
@@ -38,12 +39,12 @@ import org.apache.shiro.subject.PrincipalCollection;
...
@@ -38,12 +39,12 @@ import org.apache.shiro.subject.PrincipalCollection;
* @since 1.3.0.RELEASE
* @since 1.3.0.RELEASE
**/
**/
@Slf4j
@Slf4j
public
class
JwtRealm
extends
AuthorizingRealm
{
public
class
JwtRealm
System
extends
AuthorizingRealm
{
private
LoginRedisService
l
oginRedisService
;
private
SysLoginRedisService
sysL
oginRedisService
;
public
JwtRealm
(
LoginRedisService
l
oginRedisService
)
{
public
JwtRealm
System
(
SysLoginRedisService
sysL
oginRedisService
)
{
this
.
loginRedisService
=
l
oginRedisService
;
this
.
sysLoginRedisService
=
sysL
oginRedisService
;
}
}
@Override
@Override
...
@@ -52,21 +53,25 @@ public class JwtRealm extends AuthorizingRealm {
...
@@ -52,21 +53,25 @@ public class JwtRealm extends AuthorizingRealm {
}
}
/**
/**
*
授权认证,设置角色/权限信息
*
获取用户权限信息,包括角色以及权限。只有当触发检测用户权限时才会调用此方法,例如checkRole,checkPermission
*
*
* @param principalCollection
* @return AuthorizationInfo 权限信息
* @return
*/
*/
@Override
@Override
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principalCollection
)
{
protected
AuthorizationInfo
doGetAuthorizationInfo
(
PrincipalCollection
principalCollection
)
{
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
log
.
debug
(
"doGetAuthorizationInfo principalCollection..."
);
// 设置角色/权限信息
// 设置角色/权限信息
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
JwtToken
jwtToken
=
(
JwtToken
)
principalCollection
.
getPrimaryPrincipal
();
if
(!
jwtToken
.
getType
().
equals
(
"sys"
)){
return
null
;
}
// 获取username
// 获取username
String
username
=
jwtToken
.
getUsername
();
String
username
=
jwtToken
.
getUsername
();
// 获取登录用户角色权限信息
// 获取登录用户角色权限信息
LoginSysUserRedisVo
loginSysUserRedisVo
=
l
oginRedisService
.
getLoginSysUserRedisVo
(
username
);
LoginSysUserRedisVo
loginSysUserRedisVo
=
sysL
oginRedisService
.
getLoginSysUserRedisVo
(
username
);
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
SimpleAuthorizationInfo
authorizationInfo
=
new
SimpleAuthorizationInfo
();
// 设置角色
// 设置角色
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
loginSysUserRedisVo
.
getRoleCode
()));
authorizationInfo
.
setRoles
(
SetUtils
.
hashSet
(
loginSysUserRedisVo
.
getRoleCode
()));
// 设置权限
// 设置权限
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/service/impl/ShiroLoginServiceImpl.java
View file @
543097ed
...
@@ -19,7 +19,7 @@ package io.geekidea.springbootplus.framework.shiro.service.impl;
...
@@ -19,7 +19,7 @@ package io.geekidea.springbootplus.framework.shiro.service.impl;
import
io.geekidea.springbootplus.config.constant.CommonConstant
;
import
io.geekidea.springbootplus.config.constant.CommonConstant
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.JwtProperties
;
import
io.geekidea.springbootplus.config.properties.SpringBootPlusProperties
;
import
io.geekidea.springbootplus.config.properties.SpringBootPlusProperties
;
import
io.geekidea.springbootplus.framework.shiro.cache.LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.cache.
Sys
LoginRedisService
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.shiro.service.ShiroLoginService
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
...
@@ -50,7 +50,7 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
...
@@ -50,7 +50,7 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
@Lazy
@Lazy
@Autowired
@Autowired
private
LoginRedisService
l
oginRedisService
;
private
SysLoginRedisService
sysL
oginRedisService
;
@Lazy
@Lazy
@Autowired
@Autowired
...
@@ -92,7 +92,7 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
...
@@ -92,7 +92,7 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
// 如果token继续发往后台,则提示,此token已失效,请使用新token,不在返回新token,返回状态码:461
// 如果token继续发往后台,则提示,此token已失效,请使用新token,不在返回新token,返回状态码:461
// 如果Redis缓存中没有,JwtToken没有过期,则说明,已经刷新token
// 如果Redis缓存中没有,JwtToken没有过期,则说明,已经刷新token
boolean
exists
=
l
oginRedisService
.
exists
(
token
);
boolean
exists
=
sysL
oginRedisService
.
exists
(
token
);
if
(!
exists
)
{
if
(!
exists
)
{
httpServletResponse
.
setStatus
(
CommonConstant
.
JWT_INVALID_TOKEN_CODE
);
httpServletResponse
.
setStatus
(
CommonConstant
.
JWT_INVALID_TOKEN_CODE
);
throw
new
AuthenticationException
(
"token已无效,请使用已刷新的token"
);
throw
new
AuthenticationException
(
"token已无效,请使用已刷新的token"
);
...
@@ -103,9 +103,9 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
...
@@ -103,9 +103,9 @@ public class ShiroLoginServiceImpl implements ShiroLoginService {
// 生成新token字符串
// 生成新token字符串
String
newToken
=
JwtUtil
.
generateToken
(
username
,
salt
,
Duration
.
ofSeconds
(
expireSecond
));
String
newToken
=
JwtUtil
.
generateToken
(
username
,
salt
,
Duration
.
ofSeconds
(
expireSecond
));
// 生成新JwtToken对象
// 生成新JwtToken对象
JwtToken
newJwtToken
=
JwtToken
.
build
(
newToken
,
username
,
salt
,
expireSecond
);
JwtToken
newJwtToken
=
JwtToken
.
build
(
newToken
,
username
,
salt
,
expireSecond
,
jwtToken
.
getType
()
);
// 更新redis缓存
// 更新redis缓存
l
oginRedisService
.
refreshLoginInfo
(
token
,
username
,
newJwtToken
);
sysL
oginRedisService
.
refreshLoginInfo
(
token
,
username
,
newJwtToken
);
log
.
debug
(
"刷新token成功,原token:{},新token:{}"
,
token
,
newToken
);
log
.
debug
(
"刷新token成功,原token:{},新token:{}"
,
token
,
newToken
);
// 设置响应头
// 设置响应头
// 刷新token
// 刷新token
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/util/JwtUtil.java
View file @
543097ed
...
@@ -110,6 +110,13 @@ public class JwtUtil {
...
@@ -110,6 +110,13 @@ public class JwtUtil {
return
null
;
return
null
;
}
}
/**
* 验证token
*
* @param token
* @param salt
* @return
*/
public
static
boolean
verifyToken
(
String
token
,
String
salt
)
{
public
static
boolean
verifyToken
(
String
token
,
String
salt
)
{
try
{
try
{
Algorithm
algorithm
=
Algorithm
.
HMAC256
(
salt
);
Algorithm
algorithm
=
Algorithm
.
HMAC256
(
salt
);
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/shiro/vo/JwtTokenRedisVo.java
View file @
543097ed
...
@@ -32,6 +32,9 @@ import java.util.Date;
...
@@ -32,6 +32,9 @@ import java.util.Date;
@Accessors
(
chain
=
true
)
@Accessors
(
chain
=
true
)
public
class
JwtTokenRedisVo
implements
Serializable
{
public
class
JwtTokenRedisVo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1831633309466775223L
;
private
static
final
long
serialVersionUID
=
1831633309466775223L
;
private
String
type
;
/**
/**
* 登录ip
* 登录ip
*/
*/
...
...
framework/src/main/java/io/geekidea/springbootplus/framework/util/LoginUtil.java
View file @
543097ed
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
io
.
geekidea
.
springbootplus
.
framework
.
util
;
package
io
.
geekidea
.
springbootplus
.
framework
.
util
;
import
io.geekidea.springbootplus.config.constant.CommonRedisKey
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtTokenUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
import
io.geekidea.springbootplus.framework.shiro.vo.LoginSysUserRedisVo
;
...
@@ -55,7 +54,11 @@ public class LoginUtil {
...
@@ -55,7 +54,11 @@ public class LoginUtil {
if
(
StringUtils
.
isBlank
(
username
))
{
if
(
StringUtils
.
isBlank
(
username
))
{
return
null
;
return
null
;
}
}
return
(
LoginSysUserRedisVo
)
redisTemplate
.
opsForValue
().
get
(
String
.
format
(
CommonRedisKey
.
LOGIN_USER
,
username
));
// return (LoginSysUserRedisVo) redisTemplate.opsForValue().get(String.format(CommonRedisKey.LOGIN_USER, username));
LoginSysUserRedisVo
loginSysUserRedisVo
=
new
LoginSysUserRedisVo
();
loginSysUserRedisVo
.
setUsername
(
username
);
return
loginSysUserRedisVo
;
}
}
/**
/**
...
...
Write
Preview
Markdown
is supported
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