Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
喜欢杯子
microservices-platform
提交
2b613b2d
microservices-platform
项目概览
喜欢杯子
/
microservices-platform
与 Fork 源项目一致
Fork自
whatyn / microservices-platform
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
microservices-platform
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
2b613b2d
编写于
7月 12, 2019
作者:
zlt2000
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加Token管理模块(仅限于redis token模式):"认证管理-token管理"
上级
cc3d784d
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
366 addition
and
51 deletion
+366
-51
zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthRedisTokenStore.java
.../com/central/oauth2/common/store/AuthRedisTokenStore.java
+0
-1
zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/CustomRedisTokenStore.java
...om/central/oauth2/common/store/CustomRedisTokenStore.java
+18
-31
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/annotation/LoginClient.java
.../main/java/com/central/common/annotation/LoginClient.java
+16
-0
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/config/LoginArgResolverConfig.java
...ava/com/central/common/config/LoginArgResolverConfig.java
+4
-0
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/constant/SecurityConstants.java
...n/java/com/central/common/constant/SecurityConstants.java
+17
-0
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/resolver/ClientArgumentResolver.java
...a/com/central/common/resolver/ClientArgumentResolver.java
+53
-0
zlt-doc/sql/user-center.sql
zlt-doc/sql/user-center.sql
+3
-1
zlt-gateway/zuul-gateway/src/main/java/com/central/gateway/filter/pre/UserInfoHeaderFilter.java
.../com/central/gateway/filter/pre/UserInfoHeaderFilter.java
+8
-11
zlt-gateway/zuul-gateway/src/main/resources/application.yml
zlt-gateway/zuul-gateway/src/main/resources/application.yml
+3
-1
zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java
...n/java/com/central/oauth/controller/TokensController.java
+31
-0
zlt-uaa/src/main/java/com/central/oauth/model/TokenVo.java
zlt-uaa/src/main/java/com/central/oauth/model/TokenVo.java
+32
-0
zlt-uaa/src/main/java/com/central/oauth/service/ITokensService.java
...c/main/java/com/central/oauth/service/ITokensService.java
+18
-0
zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java
...om/central/oauth/service/impl/RedisTokensServiceImpl.java
+75
-0
zlt-uaa/src/main/resources/application.yml
zlt-uaa/src/main/resources/application.yml
+1
-1
zlt-web/back-web/src/main/resources/static/module/admin.js
zlt-web/back-web/src/main/resources/static/module/admin.js
+6
-4
zlt-web/back-web/src/main/resources/static/module/index.js
zlt-web/back-web/src/main/resources/static/module/index.js
+1
-1
zlt-web/back-web/src/main/resources/static/pages/system/tokens.html
...ck-web/src/main/resources/static/pages/system/tokens.html
+80
-0
未找到文件。
zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/AuthRedisTokenStore.java
浏览文件 @
2b613b2d
...
...
@@ -4,7 +4,6 @@ import com.central.oauth2.common.properties.SecurityProperties;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.security.oauth2.provider.ClientDetailsService
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
/**
...
...
zlt-commons/zlt-auth-client-spring-boot-starter/src/main/java/com/central/oauth2/common/store/CustomRedisTokenStore.java
浏览文件 @
2b613b2d
...
...
@@ -34,7 +34,7 @@ import java.util.List;
* 优化自Spring Security的RedisTokenStore
* 1. 支持redis cluster模式
* 2. 非cluster模式时使用pipeline减少连接次数
* 3. CLIENT_ID_TO_ACCESS集合改为list,方便业务顺序遍历
* 3. CLIENT_ID_TO_ACCESS
和UNAME_TO_ACCESS
集合改为list,方便业务顺序遍历
* 4. 自动续签token(可配置是否开启)
*
* @author zlt
...
...
@@ -43,13 +43,10 @@ import java.util.List;
public
class
CustomRedisTokenStore
implements
TokenStore
{
private
static
final
String
ACCESS
=
"access:"
;
private
static
final
String
AUTH_TO_ACCESS
=
"auth_to_access:"
;
private
static
final
String
AUTH
=
"auth:"
;
private
static
final
String
REFRESH_AUTH
=
"refresh_auth:"
;
private
static
final
String
ACCESS_TO_REFRESH
=
"access_to_refresh:"
;
private
static
final
String
REFRESH
=
"refresh:"
;
private
static
final
String
REFRESH_TO_ACCESS
=
"refresh_to_access:"
;
private
static
final
String
CLIENT_ID_TO_ACCESS
=
"client_id_to_access:"
;
private
static
final
String
UNAME_TO_ACCESS
=
"uname_to_access:"
;
/**
* 续签时间比例,当前剩余时间小于小于过期总时长的50%则续签
*/
...
...
@@ -231,7 +228,7 @@ public class CustomRedisTokenStore implements TokenStore {
byte
[]
bytes
;
RedisConnection
conn
=
getConnection
();
try
{
bytes
=
conn
.
get
(
serializeKey
(
AUTH
+
token
));
bytes
=
conn
.
get
(
serializeKey
(
SecurityConstants
.
REDIS_TOKEN_
AUTH
+
token
));
}
finally
{
conn
.
close
();
}
...
...
@@ -266,17 +263,17 @@ public class CustomRedisTokenStore implements TokenStore {
byte
[]
serializedAccessToken
=
serialize
(
token
);
byte
[]
serializedAuth
=
serialize
(
authentication
);
byte
[]
accessKey
=
serializeKey
(
ACCESS
+
token
.
getValue
());
byte
[]
authKey
=
serializeKey
(
AUTH
+
token
.
getValue
());
byte
[]
authKey
=
serializeKey
(
SecurityConstants
.
REDIS_TOKEN_
AUTH
+
token
.
getValue
());
byte
[]
authToAccessKey
=
serializeKey
(
AUTH_TO_ACCESS
+
authenticationKeyGenerator
.
extractKey
(
authentication
));
byte
[]
approvalKey
=
serializeKey
(
UNAME_TO_ACCESS
+
getApprovalKey
(
authentication
));
byte
[]
clientId
=
serializeKey
(
CLIENT_ID_TO_ACCESS
+
authentication
.
getOAuth2Request
().
getClientId
());
byte
[]
approvalKey
=
serializeKey
(
SecurityConstants
.
REDIS_
UNAME_TO_ACCESS
+
getApprovalKey
(
authentication
));
byte
[]
clientId
=
serializeKey
(
SecurityConstants
.
REDIS_
CLIENT_ID_TO_ACCESS
+
authentication
.
getOAuth2Request
().
getClientId
());
RedisConnection
conn
=
getConnection
();
try
{
byte
[]
oldAccessToken
=
null
;
//
续签的话需要查询旧的token,用于集合删除
if
(
isRenew
)
{
oldAccessToken
=
conn
.
get
(
accessKey
)
;
byte
[]
oldAccessToken
=
conn
.
get
(
accessKey
)
;
//
如果token已存在,并且不是续签的话直接返回
if
(
!
isRenew
&&
oldAccessToken
!=
null
)
{
return
;
}
this
.
openPipeline
(
conn
);
...
...
@@ -296,12 +293,12 @@ public class CustomRedisTokenStore implements TokenStore {
//如果是续签token,需要先删除集合里旧的值
if
(
oldAccessToken
!=
null
)
{
if
(!
authentication
.
isClientOnly
())
{
conn
.
sRem
(
approvalKey
,
oldAccessToken
);
conn
.
lRem
(
approvalKey
,
1
,
oldAccessToken
);
}
conn
.
lRem
(
clientId
,
1
,
oldAccessToken
);
}
if
(!
authentication
.
isClientOnly
())
{
conn
.
sAdd
(
approvalKey
,
serializedAccessToken
);
conn
.
rPush
(
approvalKey
,
serializedAccessToken
);
}
conn
.
rPush
(
clientId
,
serializedAccessToken
);
if
(
token
.
getExpiration
()
!=
null
)
{
...
...
@@ -367,7 +364,7 @@ public class CustomRedisTokenStore implements TokenStore {
public
void
removeAccessToken
(
String
tokenValue
)
{
byte
[]
accessKey
=
serializeKey
(
ACCESS
+
tokenValue
);
byte
[]
authKey
=
serializeKey
(
AUTH
+
tokenValue
);
byte
[]
authKey
=
serializeKey
(
SecurityConstants
.
REDIS_TOKEN_
AUTH
+
tokenValue
);
byte
[]
accessToRefreshKey
=
serializeKey
(
ACCESS_TO_REFRESH
+
tokenValue
);
RedisConnection
conn
=
getConnection
();
try
{
...
...
@@ -384,11 +381,11 @@ public class CustomRedisTokenStore implements TokenStore {
if
(
authentication
!=
null
)
{
String
key
=
authenticationKeyGenerator
.
extractKey
(
authentication
);
byte
[]
authToAccessKey
=
serializeKey
(
AUTH_TO_ACCESS
+
key
);
byte
[]
unameKey
=
serializeKey
(
UNAME_TO_ACCESS
+
getApprovalKey
(
authentication
));
byte
[]
clientId
=
serializeKey
(
CLIENT_ID_TO_ACCESS
+
authentication
.
getOAuth2Request
().
getClientId
());
byte
[]
unameKey
=
serializeKey
(
SecurityConstants
.
REDIS_
UNAME_TO_ACCESS
+
getApprovalKey
(
authentication
));
byte
[]
clientId
=
serializeKey
(
SecurityConstants
.
REDIS_
CLIENT_ID_TO_ACCESS
+
authentication
.
getOAuth2Request
().
getClientId
());
this
.
openPipeline
(
conn
);
conn
.
del
(
authToAccessKey
);
conn
.
sRem
(
unameKey
,
access
);
conn
.
lRem
(
unameKey
,
1
,
access
);
conn
.
lRem
(
clientId
,
1
,
access
);
conn
.
del
(
serialize
(
ACCESS
+
key
));
this
.
closePipeline
(
conn
);
...
...
@@ -499,30 +496,20 @@ public class CustomRedisTokenStore implements TokenStore {
@Override
public
Collection
<
OAuth2AccessToken
>
findTokensByClientIdAndUserName
(
String
clientId
,
String
userName
)
{
byte
[]
approvalKey
=
serializeKey
(
UNAME_TO_ACCESS
+
getApprovalKey
(
clientId
,
userName
));
byte
[]
approvalKey
=
serializeKey
(
SecurityConstants
.
REDIS_
UNAME_TO_ACCESS
+
getApprovalKey
(
clientId
,
userName
));
List
<
byte
[]>
byteList
;
RedisConnection
conn
=
getConnection
();
try
{
byteList
=
getByteLists
(
approvalKey
,
conn
);
byteList
=
conn
.
lRange
(
approvalKey
,
0
,
-
1
);
}
finally
{
conn
.
close
();
}
return
getTokenCollections
(
byteList
);
}
private
List
<
byte
[]>
getByteLists
(
byte
[]
approvalKey
,
RedisConnection
conn
)
{
List
<
byte
[]>
byteList
;
Long
size
=
conn
.
sCard
(
approvalKey
);
byteList
=
new
ArrayList
<>(
size
.
intValue
());
Cursor
<
byte
[]>
cursor
=
conn
.
sScan
(
approvalKey
,
ScanOptions
.
NONE
);
while
(
cursor
.
hasNext
())
{
byteList
.
add
(
cursor
.
next
());
}
return
byteList
;
}
@Override
public
Collection
<
OAuth2AccessToken
>
findTokensByClientId
(
String
clientId
)
{
byte
[]
key
=
serializeKey
(
CLIENT_ID_TO_ACCESS
+
clientId
);
byte
[]
key
=
serializeKey
(
SecurityConstants
.
REDIS_
CLIENT_ID_TO_ACCESS
+
clientId
);
List
<
byte
[]>
byteList
;
RedisConnection
conn
=
getConnection
();
try
{
...
...
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/annotation/LoginClient.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.common.annotation
;
import
java.lang.annotation.*
;
/**
* 请求的方法参数上添加该注解,则注入当前登录账号的应用id
* 例:public void test(@LoginClient String clientId) //注入webApp
*
* @author zlt
* @date 2018/7/24 16:44
*/
@Target
(
ElementType
.
PARAMETER
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
LoginClient
{
}
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/config/LoginArgResolverConfig.java
浏览文件 @
2b613b2d
package
com.central.common.config
;
import
com.central.common.feign.UserService
;
import
com.central.common.resolver.ClientArgumentResolver
;
import
com.central.common.resolver.TokenArgumentResolver
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Lazy
;
...
...
@@ -26,6 +27,9 @@ public class LoginArgResolverConfig implements WebMvcConfigurer {
*/
@Override
public
void
addArgumentResolvers
(
List
<
HandlerMethodArgumentResolver
>
argumentResolvers
)
{
//注入用户信息
argumentResolvers
.
add
(
new
TokenArgumentResolver
(
userService
));
//注入应用信息
argumentResolvers
.
add
(
new
ClientArgumentResolver
());
}
}
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/constant/SecurityConstants.java
浏览文件 @
2b613b2d
...
...
@@ -21,6 +21,11 @@ public interface SecurityConstants {
*/
String
ROLE_HEADER
=
"x-role-header"
;
/**
* 应用信息头
*/
String
CLIENT_HEADER
=
"x-client-header"
;
/**
* 基础角色
*/
...
...
@@ -140,4 +145,16 @@ public interface SecurityConstants {
* 默认token过期时间(1小时)
*/
Integer
ACCESS_TOKEN_VALIDITY_SECONDS
=
60
*
60
;
/**
* redis中授权token对应的key
*/
String
REDIS_TOKEN_AUTH
=
"auth:"
;
/**
* redis中应用对应的token集合的key
*/
String
REDIS_CLIENT_ID_TO_ACCESS
=
"client_id_to_access:"
;
/**
* redis中用户名对应的token集合的key
*/
String
REDIS_UNAME_TO_ACCESS
=
"uname_to_access:"
;
}
zlt-commons/zlt-common-spring-boot-starter/src/main/java/com/central/common/resolver/ClientArgumentResolver.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.common.resolver
;
import
cn.hutool.core.util.StrUtil
;
import
com.central.common.annotation.LoginClient
;
import
com.central.common.constant.SecurityConstants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
import
org.springframework.web.context.request.NativeWebRequest
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
javax.servlet.http.HttpServletRequest
;
/**
* head中的应用参数注入clientId中
*
* @author zlt
* @date 2019/7/10
*/
@Slf4j
public
class
ClientArgumentResolver
implements
HandlerMethodArgumentResolver
{
/**
* 入参筛选
*
* @param methodParameter 参数集合
* @return 格式化后的参数
*/
@Override
public
boolean
supportsParameter
(
MethodParameter
methodParameter
)
{
return
methodParameter
.
hasParameterAnnotation
(
LoginClient
.
class
)
&&
methodParameter
.
getParameterType
().
equals
(
String
.
class
);
}
/**
* @param methodParameter 入参集合
* @param modelAndViewContainer model 和 view
* @param nativeWebRequest web相关
* @param webDataBinderFactory 入参解析
* @return 包装对象
*/
@Override
public
Object
resolveArgument
(
MethodParameter
methodParameter
,
ModelAndViewContainer
modelAndViewContainer
,
NativeWebRequest
nativeWebRequest
,
WebDataBinderFactory
webDataBinderFactory
)
{
HttpServletRequest
request
=
nativeWebRequest
.
getNativeRequest
(
HttpServletRequest
.
class
);
String
clientId
=
request
.
getHeader
(
SecurityConstants
.
CLIENT_HEADER
);
if
(
StrUtil
.
isBlank
(
clientId
))
{
log
.
warn
(
"resolveArgument error clientId is empty"
);
}
return
clientId
;
}
}
zlt-doc/sql/user-center.sql
浏览文件 @
2b613b2d
...
...
@@ -121,7 +121,7 @@ INSERT INTO `sys_menu` VALUES (9, 37, '文件中心', '#!files', 'files/files.ht
INSERT
INTO
`sys_menu`
VALUES
(
10
,
37
,
'文档中心'
,
'#!swagger'
,
'http://127.0.0.1:9900/swagger-ui.html'
,
NULL
,
'layui-icon-app'
,
4
,
'2017-11-17 16:56:59'
,
'2019-01-17 20:18:48'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
11
,
12
,
'我的信息'
,
'#!myInfo'
,
'system/myInfo.html'
,
NULL
,
''
,
10
,
'2017-11-17 16:56:59'
,
'2018-09-02 06:12:24'
,
1
,
1
);
INSERT
INTO
`sys_menu`
VALUES
(
12
,
-
1
,
'认证管理'
,
'javascript:;'
,
''
,
NULL
,
'layui-icon-set'
,
1
,
'2017-11-17 16:56:59'
,
'2018-12-13 15:02:49'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
35
,
12
,
'应用管理'
,
'#!app'
,
'attestation/app.html'
,
NULL
,
'layui-icon-link'
,
9
,
'2017-11-17 16:56:59'
,
'2019-01-14 15:35:15'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
35
,
12
,
'应用管理'
,
'#!app'
,
'attestation/app.html'
,
NULL
,
'layui-icon-link'
,
5
,
'2017-11-17 16:56:59'
,
'2019-01-14 15:35:15'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
37
,
-
1
,
'系统管理'
,
'javascript:;'
,
''
,
NULL
,
'layui-icon-set'
,
2
,
'2018-08-25 10:41:58'
,
'2019-01-23 14:01:58'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
62
,
63
,
'应用监控'
,
'#!admin'
,
'http://127.0.0.1:6500/#/wallboard'
,
NULL
,
'layui-icon-chart-screen'
,
3
,
'2019-01-08 15:32:19'
,
'2019-01-17 20:22:44'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
63
,
-
1
,
'系统监控'
,
'javascript:;'
,
''
,
NULL
,
'layui-icon-set'
,
2
,
'2019-01-10 18:35:05'
,
'2019-01-10 18:35:05'
,
1
,
0
);
...
...
@@ -135,6 +135,7 @@ INSERT INTO `sys_menu` VALUES (70, 63, 'APM监控', '#!apm', 'http://127.0.0.1:8
INSERT
INTO
`sys_menu`
VALUES
(
71
,
-
1
,
'搜索管理'
,
'javascript:;'
,
''
,
NULL
,
'layui-icon-set'
,
3
,
'2018-08-25 10:41:58'
,
'2019-01-23 15:07:07'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
72
,
71
,
'索引管理'
,
'#!index'
,
'search/index_manager.html'
,
NULL
,
'layui-icon-template'
,
1
,
'2019-01-10 18:35:55'
,
'2019-01-12 00:27:20'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
73
,
71
,
'用户搜索'
,
'#!userSearch'
,
'search/user_search.html'
,
NULL
,
'layui-icon-user'
,
2
,
'2019-01-10 18:35:55'
,
'2019-01-12 00:27:20'
,
1
,
0
);
INSERT
INTO
`sys_menu`
VALUES
(
74
,
12
,
'token管理'
,
'#!tokens'
,
'system/tokens.html'
,
NULL
,
'layui-icon-unlink'
,
6
,
'2019-07-11 16:56:59'
,
'2019-07-11 16:56:59'
,
1
,
0
);
-- ----------------------------
-- Table structure for sys_role_menu
...
...
@@ -170,6 +171,7 @@ INSERT INTO `sys_role_menu` VALUES (1, 70);
INSERT
INTO
`sys_role_menu`
VALUES
(
1
,
71
);
INSERT
INTO
`sys_role_menu`
VALUES
(
1
,
72
);
INSERT
INTO
`sys_role_menu`
VALUES
(
1
,
73
);
INSERT
INTO
`sys_role_menu`
VALUES
(
1
,
74
);
INSERT
INTO
`sys_role_menu`
VALUES
(
2
,
2
);
INSERT
INTO
`sys_role_menu`
VALUES
(
2
,
3
);
INSERT
INTO
`sys_role_menu`
VALUES
(
2
,
4
);
...
...
zlt-gateway/zuul-gateway/src/main/java/com/central/gateway/filter/pre/UserInfoHeaderFilter.java
浏览文件 @
2b613b2d
...
...
@@ -2,13 +2,13 @@ package com.central.gateway.filter.pre;
import
cn.hutool.core.collection.CollectionUtil
;
import
com.central.common.constant.SecurityConstants
;
import
com.central.common.model.SysUser
;
import
com.netflix.zuul.ZuulFilter
;
import
com.netflix.zuul.context.RequestContext
;
import
org.springframework.cloud.netflix.zuul.filters.support.FilterConstants
;
import
org.springframework.security.authentication.AnonymousAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.stereotype.Component
;
import
static
org
.
springframework
.
cloud
.
netflix
.
zuul
.
filters
.
support
.
FilterConstants
.
FORM_BODY_WRAPPER_FILTER_ORDER
;
...
...
@@ -40,17 +40,14 @@ public class UserInfoHeaderFilter extends ZuulFilter {
public
Object
run
()
{
Authentication
authentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
if
(
authentication
!=
null
&&
!(
authentication
instanceof
AnonymousAuthenticationToken
))
{
Object
principal
=
authentication
.
getPrincipal
();
String
userInfo
;
if
(
principal
instanceof
SysUser
)
{
SysUser
user
=
(
SysUser
)
principal
;
userInfo
=
user
.
getUsername
();
}
else
{
//jwt的token只有name
userInfo
=
authentication
.
getName
();
}
String
username
=
authentication
.
getName
();
OAuth2Authentication
oauth2Authentication
=
(
OAuth2Authentication
)
authentication
;
String
clientId
=
oauth2Authentication
.
getOAuth2Request
().
getClientId
();
RequestContext
ctx
=
RequestContext
.
getCurrentContext
();
ctx
.
addZuulRequestHeader
(
SecurityConstants
.
USER_HEADER
,
userInfo
);
ctx
.
addZuulRequestHeader
(
SecurityConstants
.
USER_HEADER
,
username
);
ctx
.
addZuulRequestHeader
(
SecurityConstants
.
CLIENT_HEADER
,
clientId
);
ctx
.
addZuulRequestHeader
(
SecurityConstants
.
ROLE_HEADER
,
CollectionUtil
.
join
(
authentication
.
getAuthorities
(),
","
));
}
return
null
;
...
...
zlt-gateway/zuul-gateway/src/main/resources/application.yml
浏览文件 @
2b613b2d
...
...
@@ -42,7 +42,9 @@ zlt:
menusPaths
:
/api-user/menus/current
auth
:
# 配置必需认证的url
httpUrls
:
/api-uaa/clients/**
httpUrls
:
>
/api-uaa/clients/**,
/api-uaa/tokens/**
#是否开启url级别权限
urlEnabled
:
false
renew
:
...
...
zlt-uaa/src/main/java/com/central/oauth/controller/TokensController.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.oauth.controller
;
import
com.central.common.annotation.LoginClient
;
import
com.central.common.model.PageResult
;
import
com.central.oauth.model.TokenVo
;
import
com.central.oauth.service.ITokensService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.Map
;
/**
* token管理接口
*
* @author zlt
*/
@Api
(
tags
=
"Token管理"
)
@RestController
@RequestMapping
(
"/tokens"
)
public
class
TokensController
{
@Autowired
private
ITokensService
tokensService
;
@GetMapping
(
"/list"
)
@ApiOperation
(
value
=
"token列表"
)
public
PageResult
<
TokenVo
>
list
(
@RequestParam
Map
<
String
,
Object
>
params
,
@LoginClient
String
clientId
)
{
return
tokensService
.
listTokens
(
params
,
clientId
);
}
}
zlt-uaa/src/main/java/com/central/oauth/model/TokenVo.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.oauth.model
;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.io.Serializable
;
import
java.util.Date
;
/**
* @author zlt
*/
@Setter
@Getter
public
class
TokenVo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
6656955957477645319L
;
/**
* token的值
*/
private
String
tokenValue
;
/**
* 到期时间
*/
private
Date
expiration
;
/**
* 用户名
*/
private
String
username
;
/**
* 所属应用
*/
private
String
clientId
;
}
zlt-uaa/src/main/java/com/central/oauth/service/ITokensService.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.oauth.service
;
import
com.central.common.model.PageResult
;
import
com.central.oauth.model.TokenVo
;
import
java.util.Map
;
/**
* @author zlt
*/
public
interface
ITokensService
{
/**
* 查询token列表
* @param params 请求参数
* @param clientId 应用id
*/
PageResult
<
TokenVo
>
listTokens
(
Map
<
String
,
Object
>
params
,
String
clientId
);
}
zlt-uaa/src/main/java/com/central/oauth/service/impl/RedisTokensServiceImpl.java
0 → 100644
浏览文件 @
2b613b2d
package
com.central.oauth.service.impl
;
import
cn.hutool.core.util.PageUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.central.common.constant.SecurityConstants
;
import
com.central.common.model.PageResult
;
import
com.central.common.redis.template.RedisRepository
;
import
com.central.oauth.model.TokenVo
;
import
com.central.oauth.service.ITokensService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.MapUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.oauth2.common.DefaultOAuth2AccessToken
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.stereotype.Service
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
/**
* token管理服务(redis token)
*
* @author zlt
* @date 2019/7/12
*/
@Slf4j
@Service
public
class
RedisTokensServiceImpl
implements
ITokensService
{
@Autowired
private
RedisRepository
redisRepository
;
@Override
public
PageResult
<
TokenVo
>
listTokens
(
Map
<
String
,
Object
>
params
,
String
clientId
)
{
Integer
page
=
MapUtils
.
getInteger
(
params
,
"page"
);
Integer
limit
=
MapUtils
.
getInteger
(
params
,
"limit"
);
int
[]
startEnds
=
PageUtil
.
transToStartEnd
(
page
,
limit
);
//根据请求参数生成redis的key
String
redisKey
=
getRedisKey
(
params
,
clientId
);
long
size
=
redisRepository
.
length
(
redisKey
);
List
<
TokenVo
>
result
=
new
ArrayList
<>(
limit
);
//查询token集合
List
<
Object
>
tokenObjs
=
redisRepository
.
getList
(
redisKey
,
startEnds
[
0
],
startEnds
[
1
]-
1
);
if
(
tokenObjs
!=
null
)
{
for
(
Object
obj
:
tokenObjs
)
{
DefaultOAuth2AccessToken
accessToken
=
(
DefaultOAuth2AccessToken
)
obj
;
//获取用户信息
Object
authObj
=
redisRepository
.
get
(
SecurityConstants
.
REDIS_TOKEN_AUTH
+
accessToken
.
getValue
());
OAuth2Authentication
authentication
=
(
OAuth2Authentication
)
authObj
;
//构造token对象
TokenVo
tokenVo
=
new
TokenVo
();
tokenVo
.
setClientId
(
clientId
);
tokenVo
.
setTokenValue
(
accessToken
.
getValue
());
tokenVo
.
setExpiration
(
accessToken
.
getExpiration
());
tokenVo
.
setUsername
(
authentication
.
getName
());
result
.
add
(
tokenVo
);
}
}
return
PageResult
.<
TokenVo
>
builder
().
data
(
result
).
code
(
0
).
count
(
size
).
build
();
}
/**
* 根据请求参数生成redis的key
*/
private
String
getRedisKey
(
Map
<
String
,
Object
>
params
,
String
clientId
)
{
String
result
;
String
username
=
MapUtils
.
getString
(
params
,
"username"
);
if
(
StrUtil
.
isNotEmpty
(
username
))
{
result
=
SecurityConstants
.
REDIS_UNAME_TO_ACCESS
+
clientId
+
":"
+
username
;
}
else
{
result
=
SecurityConstants
.
REDIS_CLIENT_ID_TO_ACCESS
+
clientId
;
}
return
result
;
}
}
zlt-uaa/src/main/resources/application.yml
浏览文件 @
2b613b2d
...
...
@@ -29,8 +29,8 @@ zlt:
# 忽略认证的地址
httpUrls
:
>
/validata/**,
/clients,
/clients/**,
/tokens/**,
/login.html,
/css/**,
/images/**,
...
...
zlt-web/back-web/src/main/resources/static/module/admin.js
浏览文件 @
2b613b2d
...
...
@@ -84,7 +84,7 @@ layui.define(['config', 'layer'], function (exports) {
return
layer
.
open
(
param
);
},
// 封装ajax请求,返回数据类型为json
req
:
function
(
url
,
data
,
success
,
method
)
{
req
:
function
(
url
,
data
,
success
,
method
,
noHeaderToken
)
{
if
(
'
put
'
==
method
.
toLowerCase
())
{
method
=
'
PUT
'
;
}
else
if
(
'
delete
'
==
method
.
toLowerCase
())
{
...
...
@@ -99,9 +99,11 @@ layui.define(['config', 'layer'], function (exports) {
contentType
:
"
application/json
"
,
success
:
success
,
beforeSend
:
function
(
xhr
)
{
var
token
=
config
.
getToken
();
if
(
token
)
{
xhr
.
setRequestHeader
(
'
Authorization
'
,
'
bearer
'
+
token
.
access_token
);
if
(
!
noHeaderToken
)
{
let
token
=
config
.
getToken
();
if
(
token
)
{
xhr
.
setRequestHeader
(
'
Authorization
'
,
'
bearer
'
+
token
.
access_token
);
}
}
}
});
...
...
zlt-web/back-web/src/main/resources/static/module/index.js
浏览文件 @
2b613b2d
...
...
@@ -217,7 +217,7 @@ layui.define(['config', 'admin', 'layer', 'laytpl', 'element', 'form'], function
$
(
'
#btnLogout
'
).
click
(
function
()
{
layer
.
confirm
(
'
确定退出登录?
'
,
function
()
{
//通过认证中心 tuic
admin
.
req
(
'
api-uaa/oauth/remove/token
?access_token=
'
+
config
.
getToken
().
access_token
,
{},
function
(
data
)
{
admin
.
req
(
'
api-uaa/oauth/remove/token
'
,
{},
function
(
data
)
{
config
.
removeToken
();
location
.
replace
(
'
login.html
'
);
},
'
POST
'
);
...
...
zlt-web/back-web/src/main/resources/static/pages/system/tokens.html
0 → 100644
浏览文件 @
2b613b2d
<div
class=
"layui-card"
>
<div
class=
"layui-card-header"
>
<h2
class=
"header-title"
>
token管理
</h2>
<span
class=
"layui-breadcrumb pull-right"
>
<a
href=
"#!home_console"
>
首页
</a>
<a><cite>
token管理
</cite></a>
</span>
</div>
<div
class=
"layui-card-body"
>
<div
class=
"layui-form toolbar"
>
搜索:
<input
id=
"tokens-edit-search"
class=
"layui-input search-input"
type=
"text"
placeholder=
"输入用户名"
/>
 
<button
id=
"tokens-btn-search"
class=
"layui-btn icon-btn"
><i
class=
"layui-icon"
>

</i>
搜索
</button>
</div>
<!-- 数据表格 -->
<table
class=
"layui-table"
id=
"tokens-table"
lay-filter=
"tokens-table"
></table>
</div>
</div>
<!-- 表格操作列 -->
<script
type=
"text/html"
id=
"tokens-table-bar"
>
<
a
class
=
"
layui-btn layui-btn-danger layui-btn-xs
"
lay
-
event
=
"
del
"
>
删除
<
/a
>
</script>
<script>
layui
.
use
([
'
table
'
,
'
util
'
,
'
config
'
,
'
admin
'
],
function
()
{
let
table
=
layui
.
table
;
let
config
=
layui
.
config
;
let
layer
=
layui
.
layer
;
let
util
=
layui
.
util
;
let
admin
=
layui
.
admin
;
// 渲染表格
table
.
render
({
elem
:
'
#tokens-table
'
,
url
:
config
.
base_server
+
'
api-uaa/tokens/list
'
,
method
:
'
GET
'
,
headers
:{
'
Authorization
'
:
'
bearer
'
+
config
.
getToken
().
access_token
},
page
:
true
,
cols
:
[[
{
type
:
'
numbers
'
},
{
field
:
'
tokenValue
'
,
width
:
300
,
sort
:
true
,
title
:
'
token
'
},
{
sort
:
true
,
templet
:
function
(
d
)
{
return
util
.
toDateString
(
d
.
expiration
);
},
title
:
'
到期时间
'
},
{
field
:
'
username
'
,
width
:
180
,
sort
:
true
,
title
:
'
用户名
'
},
{
field
:
'
clientId
'
,
width
:
180
,
sort
:
true
,
title
:
'
所属应用
'
},
{
align
:
'
center
'
,
width
:
100
,
toolbar
:
'
#tokens-table-bar
'
,
title
:
'
操作
'
}
]]
});
// 工具条点击事件
table
.
on
(
'
tool(tokens-table)
'
,
function
(
obj
)
{
if
(
obj
.
event
===
'
del
'
)
{
// 删除
doDelete
(
obj
);
}
});
// 删除
let
doDelete
=
function
(
obj
)
{
layer
.
confirm
(
'
确定要删除吗?
'
,
function
(
i
)
{
layer
.
close
(
i
);
layer
.
load
(
2
);
admin
.
req
(
'
api-uaa/oauth/remove/token?access_token=
'
+
obj
.
data
.
tokenValue
,
{},
function
(
data
)
{
layer
.
closeAll
(
'
loading
'
);
layer
.
msg
(
'
成功
'
,
{
icon
:
1
,
time
:
500
});
obj
.
del
();
},
'
DELETE
'
,
true
);
});
};
// 搜索按钮点击事件
$
(
'
#tokens-btn-search
'
).
click
(
function
()
{
var
key
=
$
(
'
#tokens-edit-search
'
).
val
();
table
.
reload
(
'
tokens-table
'
,
{
where
:
{
username
:
key
}});
});
});
</script>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录