Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-microservice-exam
Project
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
汪想
spring-microservice-exam
Commits
3eb444be
Commit
3eb444be
authored
Apr 20, 2020
by
tangyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复refresh token失败问题
parent
21f4f0c1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
512 additions
and
9 deletions
+512
-9
LoginTypeEnum.java
...a/com/github/tangyi/common/basic/enums/LoginTypeEnum.java
+3
-3
SecurityConstant.java
...hub/tangyi/common/security/constant/SecurityConstant.java
+2
-2
CustomUserDetailsService.java
...tangyi/common/security/core/CustomUserDetailsService.java
+2
-1
auth-service.yml
config-service/src/main/resources/config/auth-service.yml
+2
-0
gateway-service.yml
config-service/src/main/resources/config/gateway-service.yml
+3
-0
README.md
modules/auth-service-parent/README.md
+1
-1
CustomAuthorizationServerConfigurer.java
...ngyi/auth/config/CustomAuthorizationServerConfigurer.java
+42
-1
CustomTokenServices.java
.../com/github/tangyi/auth/security/CustomTokenServices.java
+399
-0
CustomUserDetailsByNameServiceWrapper.java
.../auth/security/CustomUserDetailsByNameServiceWrapper.java
+37
-0
CustomUserDetailsServiceImpl.java
...ub/tangyi/auth/security/CustomUserDetailsServiceImpl.java
+20
-0
ValidateTenantAspect.java
...com/github/tangyi/auth/security/ValidateTenantAspect.java
+1
-1
No files found.
common/common-basic/src/main/java/com/github/tangyi/common/basic/enums/LoginTypeEnum.java
View file @
3eb444be
...
...
@@ -21,17 +21,17 @@ public enum LoginTypeEnum {
/**
* 验证码登录
*/
SMS
(
"SMS"
,
"验证码登录"
,
"/
api/v1/
mobile/token"
),
SMS
(
"SMS"
,
"验证码登录"
,
"/mobile/token"
),
/**
* QQ登录
*/
QQ
(
"QQ"
,
"QQ登录"
,
"/
api/v1/
mobile/token"
),
QQ
(
"QQ"
,
"QQ登录"
,
"/mobile/token"
),
/**
* 微信登录
*/
WECHAT
(
"WX"
,
"微信登录"
,
"/
api/v1/
wx/token"
);
WECHAT
(
"WX"
,
"微信登录"
,
"/wx/token"
);
/**
* 类型
...
...
common/common-security/src/main/java/com/github/tangyi/common/security/constant/SecurityConstant.java
View file @
3eb444be
...
...
@@ -29,12 +29,12 @@ public class SecurityConstant {
/**
* 手机登录URL
*/
public
static
final
String
MOBILE_TOKEN_URL
=
"/
api/v1/
mobile/token"
;
public
static
final
String
MOBILE_TOKEN_URL
=
"/mobile/token"
;
/**
* 微信登录URL
*/
public
static
final
String
WX_TOKEN_URL
=
"/
api/v1/
wx/token"
;
public
static
final
String
WX_TOKEN_URL
=
"/wx/token"
;
/**
* 租户编号请求头
...
...
common/common-security/src/main/java/com/github/tangyi/common/security/core/CustomUserDetailsService.java
View file @
3eb444be
...
...
@@ -3,6 +3,7 @@ package com.github.tangyi.common.security.core;
import
com.github.tangyi.common.security.mobile.MobileUser
;
import
com.github.tangyi.common.security.wx.WxUser
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
/**
...
...
@@ -11,7 +12,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
* @author tangyi
* @date 2019/5/28 21:05
*/
public
interface
CustomUserDetailsService
{
public
interface
CustomUserDetailsService
extends
UserDetailsService
{
/**
* 根据用户名和租户标识查询
...
...
config-service/src/main/resources/config/auth-service.yml
View file @
3eb444be
...
...
@@ -110,6 +110,8 @@ ignore:
-
/health
-
/metrics/**
-
/loggers/**
-
/mobile/token
-
/wx/token
# 集群ID生成配置
cluster
:
...
...
config-service/src/main/resources/config/gateway-service.yml
View file @
3eb444be
...
...
@@ -117,6 +117,9 @@ ignore:
-
/
-
/error
-
/favicon.ico
-
/csrf
-
/*swagger*/**
-
/**/*swagger*/**
-
/actuator/**
-
/api/auth/**
-
/api/user/**
...
...
modules/auth-service-parent/README.md
View file @
3eb444be
...
...
@@ -11,7 +11,7 @@ Auth Service
#### 账号密码+图片验证码登录
POST:
`/api/auth/api/v1/
/
token?grant_type=password&scope=read&username=admin&credential=lBTqrKS0kZixOFXeZ0HRng==&randomStr=86111562225179514&code=mf3f`
POST:
`/api/auth/api/v1/token?grant_type=password&scope=read&username=admin&credential=lBTqrKS0kZixOFXeZ0HRng==&randomStr=86111562225179514&code=mf3f`
url参数:
```
...
...
modules/auth-service-parent/auth-service/src/main/java/com/github/tangyi/auth/config/CustomAuthorizationServerConfigurer.java
View file @
3eb444be
package
com
.
github
.
tangyi
.
auth
.
config
;
import
com.github.tangyi.auth.security.CustomTokenConverter
;
import
com.github.tangyi.auth.security.CustomTokenServices
;
import
com.github.tangyi.auth.security.CustomUserDetailsByNameServiceWrapper
;
import
com.github.tangyi.common.security.core.ClientDetailsServiceImpl
;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
com.github.tangyi.common.security.exception.CustomOauthException
;
import
com.nimbusds.jose.JWSAlgorithm
;
import
com.nimbusds.jose.jwk.JWKSet
;
...
...
@@ -15,7 +18,9 @@ import org.springframework.context.annotation.Lazy;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.security.authentication.ProviderManager
;
import
org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
;
import
org.springframework.security.core.token.TokenService
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.oauth2.common.exceptions.OAuth2Exception
;
import
org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer
;
...
...
@@ -29,10 +34,12 @@ import org.springframework.security.oauth2.provider.token.TokenStore;
import
org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
;
import
org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory
;
import
org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore
;
import
org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider
;
import
javax.sql.DataSource
;
import
java.security.KeyPair
;
import
java.security.interfaces.RSAPublicKey
;
import
java.util.Arrays
;
import
java.util.Collections
;
/**
...
...
@@ -61,13 +68,16 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
*/
private
final
KeyProperties
keyProperties
;
private
final
CustomUserDetailsService
userDetailsService
;
@Autowired
public
CustomAuthorizationServerConfigurer
(
RedisConnectionFactory
redisConnectionFactory
,
DataSource
dataSource
,
KeyProperties
keyProperties
)
{
KeyProperties
keyProperties
,
CustomUserDetailsService
userDetailsService
)
{
this
.
redisConnectionFactory
=
redisConnectionFactory
;
this
.
dataSource
=
dataSource
;
this
.
keyProperties
=
keyProperties
;
this
.
userDetailsService
=
userDetailsService
;
}
/**
...
...
@@ -80,6 +90,36 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
return
new
RedisTokenStore
(
redisConnectionFactory
);
}
/**
* 防止刷新token是调用默认的loadUserByUsername,需要自定义tokenService
* @param endpoints endpoints
* @return CustomTokenServices
*/
private
CustomTokenServices
tokenService
(
AuthorizationServerEndpointsConfigurer
endpoints
)
{
CustomTokenServices
tokenServices
=
new
CustomTokenServices
();
tokenServices
.
setTokenStore
(
tokenStore
());
tokenServices
.
setSupportRefreshToken
(
true
);
tokenServices
.
setReuseRefreshToken
(
true
);
tokenServices
.
setAccessTokenValiditySeconds
(-
1
);
tokenServices
.
setClientDetailsService
(
endpoints
.
getClientDetailsService
());
tokenServices
.
setTokenEnhancer
(
jwtTokenEnhancer
());
addUserDetailsService
(
tokenServices
,
userDetailsService
);
return
tokenServices
;
}
/**
* PreAuthenticatedAuthenticationProvider自定义userDetailsService
* @param tokenServices tokenServices
* @param userDetailsService userDetailsService
*/
private
void
addUserDetailsService
(
CustomTokenServices
tokenServices
,
CustomUserDetailsService
userDetailsService
)
{
if
(
userDetailsService
!=
null
)
{
PreAuthenticatedAuthenticationProvider
provider
=
new
PreAuthenticatedAuthenticationProvider
();
provider
.
setPreAuthenticatedUserDetailsService
(
new
CustomUserDetailsByNameServiceWrapper
<>(
userDetailsService
));
tokenServices
.
setAuthenticationManager
(
new
ProviderManager
(
Collections
.
singletonList
(
provider
)));
}
}
/**
* 生成KeyPair
* @return KeyPair
...
...
@@ -141,6 +181,7 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
.
authenticationManager
(
this
.
authenticationConfiguration
.
getAuthenticationManager
())
// 将token存储到redis
.
tokenStore
(
tokenStore
())
.
tokenServices
(
tokenService
(
endpoints
))
// token增强
.
tokenEnhancer
(
jwtTokenEnhancer
())
// 异常转换
...
...
modules/auth-service-parent/auth-service/src/main/java/com/github/tangyi/auth/security/CustomTokenServices.java
0 → 100644
View file @
3eb444be
package
com
.
github
.
tangyi
.
auth
.
security
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.oauth2.common.*
;
import
org.springframework.security.oauth2.common.exceptions.InvalidGrantException
;
import
org.springframework.security.oauth2.common.exceptions.InvalidScopeException
;
import
org.springframework.security.oauth2.common.exceptions.InvalidTokenException
;
import
org.springframework.security.oauth2.provider.*
;
import
org.springframework.security.oauth2.provider.token.*
;
import
org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.Assert
;
import
java.util.Date
;
import
java.util.Set
;
import
java.util.UUID
;
/**
* @author tangyi
* @date 2020-04-19 11:32
*/
public
class
CustomTokenServices
implements
AuthorizationServerTokenServices
,
ResourceServerTokenServices
,
ConsumerTokenServices
,
InitializingBean
{
private
int
refreshTokenValiditySeconds
=
60
*
60
*
24
*
30
;
// default 30 days.
private
int
accessTokenValiditySeconds
=
60
*
60
*
12
;
// default 12 hours.
private
boolean
supportRefreshToken
=
false
;
private
boolean
reuseRefreshToken
=
true
;
private
TokenStore
tokenStore
;
private
ClientDetailsService
clientDetailsService
;
private
TokenEnhancer
accessTokenEnhancer
;
private
AuthenticationManager
authenticationManager
;
/**
* Initialize these token services. If no random generator is set, one will be created.
*/
public
void
afterPropertiesSet
()
throws
Exception
{
Assert
.
notNull
(
tokenStore
,
"tokenStore must be set"
);
}
@Transactional
public
OAuth2AccessToken
createAccessToken
(
OAuth2Authentication
authentication
)
throws
AuthenticationException
{
OAuth2AccessToken
existingAccessToken
=
tokenStore
.
getAccessToken
(
authentication
);
OAuth2RefreshToken
refreshToken
=
null
;
if
(
existingAccessToken
!=
null
)
{
if
(
existingAccessToken
.
isExpired
())
{
if
(
existingAccessToken
.
getRefreshToken
()
!=
null
)
{
refreshToken
=
existingAccessToken
.
getRefreshToken
();
// The token store could remove the refresh token when the
// access token is removed, but we want to
// be sure...
tokenStore
.
removeRefreshToken
(
refreshToken
);
}
tokenStore
.
removeAccessToken
(
existingAccessToken
);
}
else
{
// Re-store the access token in case the authentication has changed
tokenStore
.
storeAccessToken
(
existingAccessToken
,
authentication
);
return
existingAccessToken
;
}
}
// Only create a new refresh token if there wasn't an existing one
// associated with an expired access token.
// Clients might be holding existing refresh tokens, so we re-use it in
// the case that the old access token
// expired.
if
(
refreshToken
==
null
)
{
refreshToken
=
createRefreshToken
(
authentication
);
}
// But the refresh token itself might need to be re-issued if it has
// expired.
else
if
(
refreshToken
instanceof
ExpiringOAuth2RefreshToken
)
{
ExpiringOAuth2RefreshToken
expiring
=
(
ExpiringOAuth2RefreshToken
)
refreshToken
;
if
(
System
.
currentTimeMillis
()
>
expiring
.
getExpiration
().
getTime
())
{
refreshToken
=
createRefreshToken
(
authentication
);
}
}
OAuth2AccessToken
accessToken
=
createAccessToken
(
authentication
,
refreshToken
);
tokenStore
.
storeAccessToken
(
accessToken
,
authentication
);
// In case it was modified
refreshToken
=
accessToken
.
getRefreshToken
();
if
(
refreshToken
!=
null
)
{
tokenStore
.
storeRefreshToken
(
refreshToken
,
authentication
);
}
return
accessToken
;
}
@Transactional
(
noRollbackFor
={
InvalidTokenException
.
class
,
InvalidGrantException
.
class
})
public
OAuth2AccessToken
refreshAccessToken
(
String
refreshTokenValue
,
TokenRequest
tokenRequest
)
throws
AuthenticationException
{
if
(!
supportRefreshToken
)
{
throw
new
InvalidGrantException
(
"Invalid refresh token: "
+
refreshTokenValue
);
}
OAuth2RefreshToken
refreshToken
=
tokenStore
.
readRefreshToken
(
refreshTokenValue
);
if
(
refreshToken
==
null
)
{
throw
new
InvalidGrantException
(
"Invalid refresh token: "
+
refreshTokenValue
);
}
OAuth2Authentication
authentication
=
tokenStore
.
readAuthenticationForRefreshToken
(
refreshToken
);
if
(
this
.
authenticationManager
!=
null
&&
!
authentication
.
isClientOnly
())
{
// The client has already been authenticated, but the user authentication might be old now, so give it a
// chance to re-authenticate.
Authentication
user
=
new
PreAuthenticatedAuthenticationToken
(
authentication
.
getUserAuthentication
(),
""
,
authentication
.
getAuthorities
());
user
=
authenticationManager
.
authenticate
(
user
);
Object
details
=
authentication
.
getDetails
();
authentication
=
new
OAuth2Authentication
(
authentication
.
getOAuth2Request
(),
user
);
authentication
.
setDetails
(
details
);
}
String
clientId
=
authentication
.
getOAuth2Request
().
getClientId
();
if
(
clientId
==
null
||
!
clientId
.
equals
(
tokenRequest
.
getClientId
()))
{
throw
new
InvalidGrantException
(
"Wrong client for this refresh token: "
+
refreshTokenValue
);
}
// clear out any access tokens already associated with the refresh
// token.
tokenStore
.
removeAccessTokenUsingRefreshToken
(
refreshToken
);
if
(
isExpired
(
refreshToken
))
{
tokenStore
.
removeRefreshToken
(
refreshToken
);
throw
new
InvalidTokenException
(
"Invalid refresh token (expired): "
+
refreshToken
);
}
authentication
=
createRefreshedAuthentication
(
authentication
,
tokenRequest
);
if
(!
reuseRefreshToken
)
{
tokenStore
.
removeRefreshToken
(
refreshToken
);
refreshToken
=
createRefreshToken
(
authentication
);
}
OAuth2AccessToken
accessToken
=
createAccessToken
(
authentication
,
refreshToken
);
tokenStore
.
storeAccessToken
(
accessToken
,
authentication
);
if
(!
reuseRefreshToken
)
{
tokenStore
.
storeRefreshToken
(
accessToken
.
getRefreshToken
(),
authentication
);
}
return
accessToken
;
}
public
OAuth2AccessToken
getAccessToken
(
OAuth2Authentication
authentication
)
{
return
tokenStore
.
getAccessToken
(
authentication
);
}
/**
* Create a refreshed authentication.
*
* @param authentication The authentication.
* @param request The scope for the refreshed token.
* @return The refreshed authentication.
* @throws InvalidScopeException If the scope requested is invalid or wider than the original scope.
*/
private
OAuth2Authentication
createRefreshedAuthentication
(
OAuth2Authentication
authentication
,
TokenRequest
request
)
{
OAuth2Authentication
narrowed
=
authentication
;
Set
<
String
>
scope
=
request
.
getScope
();
OAuth2Request
clientAuth
=
authentication
.
getOAuth2Request
().
refresh
(
request
);
if
(
scope
!=
null
&&
!
scope
.
isEmpty
())
{
Set
<
String
>
originalScope
=
clientAuth
.
getScope
();
if
(
originalScope
==
null
||
!
originalScope
.
containsAll
(
scope
))
{
throw
new
InvalidScopeException
(
"Unable to narrow the scope of the client authentication to "
+
scope
+
"."
,
originalScope
);
}
else
{
clientAuth
=
clientAuth
.
narrowScope
(
scope
);
}
}
narrowed
=
new
OAuth2Authentication
(
clientAuth
,
authentication
.
getUserAuthentication
());
return
narrowed
;
}
protected
boolean
isExpired
(
OAuth2RefreshToken
refreshToken
)
{
if
(
refreshToken
instanceof
ExpiringOAuth2RefreshToken
)
{
ExpiringOAuth2RefreshToken
expiringToken
=
(
ExpiringOAuth2RefreshToken
)
refreshToken
;
return
expiringToken
.
getExpiration
()
==
null
||
System
.
currentTimeMillis
()
>
expiringToken
.
getExpiration
().
getTime
();
}
return
false
;
}
public
OAuth2AccessToken
readAccessToken
(
String
accessToken
)
{
return
tokenStore
.
readAccessToken
(
accessToken
);
}
public
OAuth2Authentication
loadAuthentication
(
String
accessTokenValue
)
throws
AuthenticationException
,
InvalidTokenException
{
OAuth2AccessToken
accessToken
=
tokenStore
.
readAccessToken
(
accessTokenValue
);
if
(
accessToken
==
null
)
{
throw
new
InvalidTokenException
(
"Invalid access token: "
+
accessTokenValue
);
}
else
if
(
accessToken
.
isExpired
())
{
tokenStore
.
removeAccessToken
(
accessToken
);
throw
new
InvalidTokenException
(
"Access token expired: "
+
accessTokenValue
);
}
OAuth2Authentication
result
=
tokenStore
.
readAuthentication
(
accessToken
);
if
(
result
==
null
)
{
// in case of race condition
throw
new
InvalidTokenException
(
"Invalid access token: "
+
accessTokenValue
);
}
if
(
clientDetailsService
!=
null
)
{
String
clientId
=
result
.
getOAuth2Request
().
getClientId
();
try
{
clientDetailsService
.
loadClientByClientId
(
clientId
);
}
catch
(
ClientRegistrationException
e
)
{
throw
new
InvalidTokenException
(
"Client not valid: "
+
clientId
,
e
);
}
}
return
result
;
}
public
String
getClientId
(
String
tokenValue
)
{
OAuth2Authentication
authentication
=
tokenStore
.
readAuthentication
(
tokenValue
);
if
(
authentication
==
null
)
{
throw
new
InvalidTokenException
(
"Invalid access token: "
+
tokenValue
);
}
OAuth2Request
clientAuth
=
authentication
.
getOAuth2Request
();
if
(
clientAuth
==
null
)
{
throw
new
InvalidTokenException
(
"Invalid access token (no client id): "
+
tokenValue
);
}
return
clientAuth
.
getClientId
();
}
public
boolean
revokeToken
(
String
tokenValue
)
{
OAuth2AccessToken
accessToken
=
tokenStore
.
readAccessToken
(
tokenValue
);
if
(
accessToken
==
null
)
{
return
false
;
}
if
(
accessToken
.
getRefreshToken
()
!=
null
)
{
tokenStore
.
removeRefreshToken
(
accessToken
.
getRefreshToken
());
}
tokenStore
.
removeAccessToken
(
accessToken
);
return
true
;
}
private
OAuth2RefreshToken
createRefreshToken
(
OAuth2Authentication
authentication
)
{
if
(!
isSupportRefreshToken
(
authentication
.
getOAuth2Request
()))
{
return
null
;
}
int
validitySeconds
=
getRefreshTokenValiditySeconds
(
authentication
.
getOAuth2Request
());
String
value
=
UUID
.
randomUUID
().
toString
();
if
(
validitySeconds
>
0
)
{
return
new
DefaultExpiringOAuth2RefreshToken
(
value
,
new
Date
(
System
.
currentTimeMillis
()
+
(
validitySeconds
*
1000L
)));
}
return
new
DefaultOAuth2RefreshToken
(
value
);
}
private
OAuth2AccessToken
createAccessToken
(
OAuth2Authentication
authentication
,
OAuth2RefreshToken
refreshToken
)
{
DefaultOAuth2AccessToken
token
=
new
DefaultOAuth2AccessToken
(
UUID
.
randomUUID
().
toString
());
int
validitySeconds
=
getAccessTokenValiditySeconds
(
authentication
.
getOAuth2Request
());
if
(
validitySeconds
>
0
)
{
token
.
setExpiration
(
new
Date
(
System
.
currentTimeMillis
()
+
(
validitySeconds
*
1000L
)));
}
token
.
setRefreshToken
(
refreshToken
);
token
.
setScope
(
authentication
.
getOAuth2Request
().
getScope
());
return
accessTokenEnhancer
!=
null
?
accessTokenEnhancer
.
enhance
(
token
,
authentication
)
:
token
;
}
/**
* The access token validity period in seconds
*
* @param clientAuth the current authorization request
* @return the access token validity period in seconds
*/
protected
int
getAccessTokenValiditySeconds
(
OAuth2Request
clientAuth
)
{
if
(
clientDetailsService
!=
null
)
{
ClientDetails
client
=
clientDetailsService
.
loadClientByClientId
(
clientAuth
.
getClientId
());
Integer
validity
=
client
.
getAccessTokenValiditySeconds
();
if
(
validity
!=
null
)
{
return
validity
;
}
}
return
accessTokenValiditySeconds
;
}
/**
* The refresh token validity period in seconds
*
* @param clientAuth the current authorization request
* @return the refresh token validity period in seconds
*/
protected
int
getRefreshTokenValiditySeconds
(
OAuth2Request
clientAuth
)
{
if
(
clientDetailsService
!=
null
)
{
ClientDetails
client
=
clientDetailsService
.
loadClientByClientId
(
clientAuth
.
getClientId
());
Integer
validity
=
client
.
getRefreshTokenValiditySeconds
();
if
(
validity
!=
null
)
{
return
validity
;
}
}
return
refreshTokenValiditySeconds
;
}
/**
* Is a refresh token supported for this client (or the global setting if
* {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set.
*
* @param clientAuth the current authorization request
* @return boolean to indicate if refresh token is supported
*/
protected
boolean
isSupportRefreshToken
(
OAuth2Request
clientAuth
)
{
if
(
clientDetailsService
!=
null
)
{
ClientDetails
client
=
clientDetailsService
.
loadClientByClientId
(
clientAuth
.
getClientId
());
return
client
.
getAuthorizedGrantTypes
().
contains
(
"refresh_token"
);
}
return
this
.
supportRefreshToken
;
}
/**
* An access token enhancer that will be applied to a new token before it is saved in the token store.
*
* @param accessTokenEnhancer the access token enhancer to set
*/
public
void
setTokenEnhancer
(
TokenEnhancer
accessTokenEnhancer
)
{
this
.
accessTokenEnhancer
=
accessTokenEnhancer
;
}
/**
* The validity (in seconds) of the refresh token. If less than or equal to zero then the tokens will be
* non-expiring.
*
* @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token.
*/
public
void
setRefreshTokenValiditySeconds
(
int
refreshTokenValiditySeconds
)
{
this
.
refreshTokenValiditySeconds
=
refreshTokenValiditySeconds
;
}
/**
* The default validity (in seconds) of the access token. Zero or negative for non-expiring tokens. If a client
* details service is set the validity period will be read from the client, defaulting to this value if not defined
* by the client.
*
* @param accessTokenValiditySeconds The validity (in seconds) of the access token.
*/
public
void
setAccessTokenValiditySeconds
(
int
accessTokenValiditySeconds
)
{
this
.
accessTokenValiditySeconds
=
accessTokenValiditySeconds
;
}
/**
* Whether to support the refresh token.
*
* @param supportRefreshToken Whether to support the refresh token.
*/
public
void
setSupportRefreshToken
(
boolean
supportRefreshToken
)
{
this
.
supportRefreshToken
=
supportRefreshToken
;
}
/**
* Whether to reuse refresh tokens (until expired).
*
* @param reuseRefreshToken Whether to reuse refresh tokens (until expired).
*/
public
void
setReuseRefreshToken
(
boolean
reuseRefreshToken
)
{
this
.
reuseRefreshToken
=
reuseRefreshToken
;
}
/**
* The persistence strategy for token storage.
*
* @param tokenStore the store for access and refresh tokens.
*/
public
void
setTokenStore
(
TokenStore
tokenStore
)
{
this
.
tokenStore
=
tokenStore
;
}
/**
* An authentication manager that will be used (if provided) to check the user authentication when a token is
* refreshed.
*
* @param authenticationManager the authenticationManager to set
*/
public
void
setAuthenticationManager
(
AuthenticationManager
authenticationManager
)
{
this
.
authenticationManager
=
authenticationManager
;
}
/**
* The client details service to use for looking up clients (if necessary). Optional if the access token expiry is
* set globally via {@link #setAccessTokenValiditySeconds(int)}.
*
* @param clientDetailsService the client details service
*/
public
void
setClientDetailsService
(
ClientDetailsService
clientDetailsService
)
{
this
.
clientDetailsService
=
clientDetailsService
;
}
}
modules/auth-service-parent/auth-service/src/main/java/com/github/tangyi/auth/security/CustomUserDetailsByNameServiceWrapper.java
0 → 100644
View file @
3eb444be
package
com
.
github
.
tangyi
.
auth
.
security
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.userdetails.AuthenticationUserDetailsService
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.util.Assert
;
/**
* @author tangyi
* @date 2020-04-19 11:32
*/
public
class
CustomUserDetailsByNameServiceWrapper
<
T
extends
Authentication
>
implements
AuthenticationUserDetailsService
<
T
>,
InitializingBean
{
private
UserDetailsService
userDetailsService
=
null
;
public
CustomUserDetailsByNameServiceWrapper
()
{
}
public
CustomUserDetailsByNameServiceWrapper
(
UserDetailsService
userDetailsService
)
{
Assert
.
notNull
(
userDetailsService
,
"userDetailsService cannot be null."
);
this
.
userDetailsService
=
userDetailsService
;
}
public
void
afterPropertiesSet
()
{
Assert
.
notNull
(
this
.
userDetailsService
,
"UserDetailsService must be set"
);
}
public
UserDetails
loadUserDetails
(
T
authentication
)
throws
UsernameNotFoundException
{
return
this
.
userDetailsService
.
loadUserByUsername
(
authentication
.
getName
());
}
public
void
setUserDetailsService
(
UserDetailsService
aUserDetailsService
)
{
this
.
userDetailsService
=
aUserDetailsService
;
}
}
modules/auth-service-parent/auth-service/src/main/java/com/github/tangyi/auth/security/CustomUserDetailsServiceImpl.java
View file @
3eb444be
...
...
@@ -15,6 +15,7 @@ import com.github.tangyi.common.core.utils.ResponseUtil;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
com.github.tangyi.common.security.core.GrantedAuthorityImpl
;
import
com.github.tangyi.common.security.mobile.MobileUser
;
import
com.github.tangyi.common.security.tenant.TenantContextHolder
;
import
com.github.tangyi.common.security.wx.WxUser
;
import
com.github.tangyi.user.api.dto.UserDto
;
import
com.github.tangyi.user.api.enums.IdentityType
;
...
...
@@ -48,6 +49,25 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
/**
* 加载用户信息
* @param username username
* @return UserDetails
* @throws UsernameNotFoundException
*/
@Override
public
UserDetails
loadUserByUsername
(
String
username
)
throws
UsernameNotFoundException
{
long
start
=
System
.
currentTimeMillis
();
ResponseBean
<
UserVo
>
userVoResponseBean
=
userServiceClient
.
findUserByIdentifier
(
username
,
TenantContextHolder
.
getTenantCode
());
if
(!
ResponseUtil
.
isSuccess
(
userVoResponseBean
))
throw
new
ServiceException
(
GET_USER_INFO_FAIL
+
userVoResponseBean
.
getMsg
());
UserVo
userVo
=
userVoResponseBean
.
getData
();
if
(
userVo
==
null
)
throw
new
UsernameNotFoundException
(
"user does not exist"
);
return
new
CustomUserDetails
(
username
,
userVo
.
getCredential
(),
CommonConstant
.
STATUS_NORMAL
.
equals
(
userVo
.
getStatus
()),
getAuthority
(
userVo
),
userVo
.
getTenantCode
(),
userVo
.
getId
(),
start
,
LoginTypeEnum
.
PWD
);
}
/**
* 加载用户信息
*
* @param tenantCode 租户标识
* @param username 用户名
...
...
modules/auth-service-parent/auth-service/src/main/java/com/github/tangyi/auth/security/ValidateTenantAspect.java
View file @
3eb444be
...
...
@@ -26,7 +26,7 @@ public class ValidateTenantAspect {
private
final
UserServiceClient
userServiceClient
;
@Before
(
"execution(* com.github.tangyi.auth.security.CustomUserDetailsServiceImpl.
load*
(..)) && args(tenantCode,..)"
)
@Before
(
"execution(* com.github.tangyi.auth.security.CustomUserDetailsServiceImpl.
*AndTenantCode
(..)) && args(tenantCode,..)"
)
public
void
validateTenantCode
(
String
tenantCode
)
throws
TenantNotFoundException
{
// 获取tenantCode
if
(
StringUtils
.
isBlank
(
tenantCode
))
...
...
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