Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
Y
yifu-mvp
Project
Project
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
fangxinjiang
yifu-mvp
Commits
cbd8c0d1
Commit
cbd8c0d1
authored
Nov 24, 2022
by
fangxinjiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
权限配置页面
parent
596dbc81
Show whitespace changes
Inline
Side-by-side
Showing
45 changed files
with
0 additions
and
3587 deletions
+0
-3587
EnableYifuResourceServer.java
.../common/security/annotation/EnableYifuResourceServer.java
+0
-44
Inner.java
....cloud.plus.v1/yifu/common/security/annotation/Inner.java
+0
-44
PermissionService.java
....v1/yifu/common/security/component/PermissionService.java
+0
-52
PermitAllUrlProperties.java
...ifu/common/security/component/PermitAllUrlProperties.java
+0
-92
ResourceAuthExceptionEntryPoint.java
...n/security/component/ResourceAuthExceptionEntryPoint.java
+0
-65
YifuAuth2ExceptionSerializer.java
...mmon/security/component/YifuAuth2ExceptionSerializer.java
+0
-50
YifuBearerTokenExtractor.java
...u/common/security/component/YifuBearerTokenExtractor.java
+0
-51
YifuDaoAuthenticationProvider.java
...mon/security/component/YifuDaoAuthenticationProvider.java
+0
-174
YifuLocalResourceServerTokenServices.java
...urity/component/YifuLocalResourceServerTokenServices.java
+0
-83
YifuRedisTokenStore.java
...1/yifu/common/security/component/YifuRedisTokenStore.java
+0
-478
YifuResourceServerAutoConfiguration.java
...curity/component/YifuResourceServerAutoConfiguration.java
+0
-54
YifuResourceServerConfigurerAdapter.java
...curity/component/YifuResourceServerConfigurerAdapter.java
+0
-78
YifuResourceServerTokenRelayAutoConfiguration.java
...ponent/YifuResourceServerTokenRelayAutoConfiguration.java
+0
-74
YifuSecurityBeanDefinitionRegistrar.java
...curity/component/YifuSecurityBeanDefinitionRegistrar.java
+0
-51
YifuSecurityInnerAspect.java
...fu/common/security/component/YifuSecurityInnerAspect.java
+0
-68
YifuSecurityMessageSourceConfiguration.java
...ity/component/YifuSecurityMessageSourceConfiguration.java
+0
-43
YifuTokenStoreAutoCleanSchedule.java
...n/security/component/YifuTokenStoreAutoCleanSchedule.java
+0
-31
YifuTokenStoreAutoConfiguration.java
...n/security/component/YifuTokenStoreAutoConfiguration.java
+0
-21
YifuWebResponseExceptionTranslator.java
...ecurity/component/YifuWebResponseExceptionTranslator.java
+0
-111
DataException.java
...plus.v1/yifu/common/security/exception/DataException.java
+0
-18
ForbiddenException.java
...v1/yifu/common/security/exception/ForbiddenException.java
+0
-44
GlobalExceptionHandler.java
...ifu/common/security/exception/GlobalExceptionHandler.java
+0
-155
InvalidException.java
...s.v1/yifu/common/security/exception/InvalidException.java
+0
-43
MethodNotAllowed.java
...s.v1/yifu/common/security/exception/MethodNotAllowed.java
+0
-44
ServerErrorException.java
.../yifu/common/security/exception/ServerErrorException.java
+0
-44
TokenInvalidException.java
...yifu/common/security/exception/TokenInvalidException.java
+0
-47
UnauthorizedException.java
...yifu/common/security/exception/UnauthorizedException.java
+0
-44
YifuAuth2Exception.java
...v1/yifu/common/security/exception/YifuAuth2Exception.java
+0
-43
YifuFeignClientConfiguration.java
...u/common/security/feign/YifuFeignClientConfiguration.java
+0
-39
YifuFeignClientInterceptor.java
...ifu/common/security/feign/YifuFeignClientInterceptor.java
+0
-73
CustomAppAuthenticationProvider.java
...ommon/security/grant/CustomAppAuthenticationProvider.java
+0
-103
CustomAppAuthenticationToken.java
...u/common/security/grant/CustomAppAuthenticationToken.java
+0
-48
ResourceOwnerCustomAppTokenGranter.java
...on/security/grant/ResourceOwnerCustomAppTokenGranter.java
+0
-78
AbstractAuthenticationFailureEventHandler.java
...ty/handler/AbstractAuthenticationFailureEventHandler.java
+0
-51
AbstractAuthenticationSuccessEventHandler.java
...ty/handler/AbstractAuthenticationSuccessEventHandler.java
+0
-51
AbstractLogoutSuccessEventHandler.java
...n/security/handler/AbstractLogoutSuccessEventHandler.java
+0
-50
FormAuthenticationFailureHandler.java
...on/security/handler/FormAuthenticationFailureHandler.java
+0
-55
SsoLogoutSuccessHandler.java
...yifu/common/security/handler/SsoLogoutSuccessHandler.java
+0
-41
YifuAppUserDetailsServiceImpl.java
...ommon/security/service/YifuAppUserDetailsServiceImpl.java
+0
-86
YifuClientDetailsService.java
...ifu/common/security/service/YifuClientDetailsService.java
+0
-51
YifuCustomTokenServices.java
...yifu/common/security/service/YifuCustomTokenServices.java
+0
-382
YifuUserDetailsService.java
.../yifu/common/security/service/YifuUserDetailsService.java
+0
-88
YifuUserDetailsServiceImpl.java
...u/common/security/service/YifuUserDetailsServiceImpl.java
+0
-79
AuthUtils.java
...fu.cloud.plus.v1/yifu/common/security/util/AuthUtils.java
+0
-81
SecurityUtils.java
...loud.plus.v1/yifu/common/security/util/SecurityUtils.java
+0
-85
No files found.
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/annotation/EnableYifuResourceServer.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
annotation
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuResourceServerAutoConfiguration
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuResourceServerTokenRelayAutoConfiguration
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuSecurityBeanDefinitionRegistrar
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
;
import
org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer
;
import
java.lang.annotation.*
;
/**
* @author lengleng
* @date 2019/03/08
* <p>
* 资源服务注解
*/
@Documented
@Inherited
@EnableResourceServer
@Target
({
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@EnableGlobalMethodSecurity
(
prePostEnabled
=
true
)
@Import
({
YifuResourceServerAutoConfiguration
.
class
,
YifuSecurityBeanDefinitionRegistrar
.
class
,
YifuResourceServerTokenRelayAutoConfiguration
.
class
})
public
@interface
EnableYifuResourceServer
{
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/annotation/Inner.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
annotation
;
import
java.lang.annotation.*
;
/**
* 服务调用不鉴权注解
*
* @author lengleng
* @date 2020-06-14
*/
@Target
({
ElementType
.
METHOD
,
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
Inner
{
/**
* 是否AOP统一处理
* @return false, true
*/
boolean
value
()
default
true
;
/**
* 需要特殊判空的字段(预留)
* @return {}
*/
String
[]
field
()
default
{};
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/PermissionService.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.core.util.ArrayUtil
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.util.PatternMatchUtils
;
import
org.springframework.util.StringUtils
;
import
java.util.Collection
;
/**
* @author lengleng
* @date 2019/2/1 接口权限判断工具
*/
public
class
PermissionService
{
/**
* 判断接口是否有任意xxx,xxx权限
* @param permissions 权限
* @return {boolean}
*/
public
boolean
hasPermission
(
String
...
permissions
)
{
if
(
ArrayUtil
.
isEmpty
(
permissions
))
{
return
false
;
}
Authentication
authentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
if
(
authentication
==
null
)
{
return
false
;
}
Collection
<?
extends
GrantedAuthority
>
authorities
=
authentication
.
getAuthorities
();
return
authorities
.
stream
().
map
(
GrantedAuthority:
:
getAuthority
).
filter
(
StringUtils:
:
hasText
)
.
anyMatch
(
x
->
PatternMatchUtils
.
simpleMatch
(
permissions
,
x
));
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/PermitAllUrlProperties.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.core.util.ReUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContextAware
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.web.method.HandlerMethod
;
import
org.springframework.web.servlet.mvc.method.RequestMappingInfo
;
import
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.regex.Pattern
;
/**
* @author lengleng
* @date 2020-03-11
* <p>
* 资源服务器对外直接暴露URL,如果设置contex-path 要特殊处理
*/
@Slf4j
@ConfigurationProperties
(
prefix
=
"security.oauth2.ignore"
)
public
class
PermitAllUrlProperties
implements
InitializingBean
,
ApplicationContextAware
{
private
static
final
Pattern
PATTERN
=
Pattern
.
compile
(
"\\{(.*?)\\}"
);
private
ApplicationContext
applicationContext
;
@Getter
@Setter
private
List
<
String
>
urls
=
new
ArrayList
<>();
@Override
public
void
afterPropertiesSet
()
{
RequestMappingHandlerMapping
mapping
=
applicationContext
.
getBean
(
RequestMappingHandlerMapping
.
class
);
Map
<
RequestMappingInfo
,
HandlerMethod
>
map
=
mapping
.
getHandlerMethods
();
map
.
keySet
().
forEach
(
info
->
{
HandlerMethod
handlerMethod
=
map
.
get
(
info
);
// 获取方法上边的注解 替代path variable 为 *
Inner
method
=
AnnotationUtils
.
findAnnotation
(
handlerMethod
.
getMethod
(),
Inner
.
class
);
if
(
null
!=
method
&&
null
!=
info
.
getPatternsCondition
()){
Optional
.
ofNullable
(
method
).
ifPresent
(
inner
->
info
.
getPatternsCondition
().
getPatterns
()
.
forEach
(
url
->
urls
.
add
(
ReUtil
.
replaceAll
(
url
.
toString
(),
PATTERN
,
"*"
))));
}
// 获取类上边的注解, 替代path variable 为 *
Inner
controller
=
AnnotationUtils
.
findAnnotation
(
handlerMethod
.
getBeanType
(),
Inner
.
class
);
if
(
null
!=
controller
&&
null
!=
info
.
getPatternsCondition
())
Optional
.
ofNullable
(
controller
).
ifPresent
(
inner
->
info
.
getPatternsCondition
().
getPatterns
()
.
forEach
(
url
->
urls
.
add
(
ReUtil
.
replaceAll
(
url
.
toString
(),
PATTERN
,
"*"
))));
});
if
(
Common
.
isNotNull
(
urls
)){
for
(
String
url:
urls
){
log
.
info
(
url
.
toString
());
}
}
}
@Override
public
void
setApplicationContext
(
ApplicationContext
context
)
throws
BeansException
{
this
.
applicationContext
=
context
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/ResourceAuthExceptionEntryPoint.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.http.HttpStatus
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
org.springframework.security.authentication.InsufficientAuthenticationException
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.web.AuthenticationEntryPoint
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.PrintWriter
;
/**
* @author lengleng
* @date 2019/2/1 客户端异常处理 1. 可以根据 AuthenticationException 不同细化异常处理
*/
@RequiredArgsConstructor
public
class
ResourceAuthExceptionEntryPoint
implements
AuthenticationEntryPoint
{
private
final
ObjectMapper
objectMapper
;
@Override
@SneakyThrows
public
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
authException
)
{
response
.
setCharacterEncoding
(
CommonConstants
.
UTF8
);
response
.
setContentType
(
CommonConstants
.
CONTENT_TYPE
);
R
<
String
>
result
=
new
R
<>();
result
.
setCode
(
CommonConstants
.
FAIL
);
response
.
setStatus
(
HttpStatus
.
HTTP_UNAUTHORIZED
);
if
(
authException
!=
null
)
{
result
.
setMsg
(
"error"
);
result
.
setData
(
authException
.
getMessage
());
}
// 针对令牌过期返回特殊的 424
if
(
authException
instanceof
InsufficientAuthenticationException
)
{
response
.
setStatus
(
org
.
springframework
.
http
.
HttpStatus
.
FAILED_DEPENDENCY
.
value
());
result
.
setMsg
(
"token expire"
);
}
PrintWriter
printWriter
=
response
.
getWriter
();
printWriter
.
append
(
objectMapper
.
writeValueAsString
(
result
));
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuAuth2ExceptionSerializer.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.ser.std.StdSerializer
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.security.exception.YifuAuth2Exception
;
import
lombok.SneakyThrows
;
/**
* @author lengleng
* @date 2019/2/1
* <p>
* OAuth2 异常格式化
*/
public
class
YifuAuth2ExceptionSerializer
extends
StdSerializer
<
YifuAuth2Exception
>
{
public
YifuAuth2ExceptionSerializer
()
{
super
(
YifuAuth2Exception
.
class
);
}
@Override
@SneakyThrows
public
void
serialize
(
YifuAuth2Exception
value
,
JsonGenerator
gen
,
SerializerProvider
provider
)
{
gen
.
writeStartObject
();
gen
.
writeObjectField
(
"code"
,
CommonConstants
.
FAIL
);
gen
.
writeStringField
(
"msg"
,
value
.
getMessage
());
gen
.
writeStringField
(
"data"
,
value
.
getErrorCode
());
// 资源服务器会读取这个字段
gen
.
writeStringField
(
"error"
,
value
.
getMessage
());
gen
.
writeEndObject
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuBearerTokenExtractor.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.PathMatcher
;
import
javax.servlet.http.HttpServletRequest
;
/**
* 改造 {@link BearerTokenExtractor} 对公开权限的请求不进行校验
*
* @author caiqy
* @date 2020.05.15
*/
public
class
YifuBearerTokenExtractor
extends
BearerTokenExtractor
{
private
final
PathMatcher
pathMatcher
;
private
final
PermitAllUrlProperties
urlProperties
;
public
YifuBearerTokenExtractor
(
PermitAllUrlProperties
urlProperties
)
{
this
.
urlProperties
=
urlProperties
;
this
.
pathMatcher
=
new
AntPathMatcher
();
}
@Override
public
Authentication
extract
(
HttpServletRequest
request
)
{
boolean
match
=
urlProperties
.
getUrls
().
stream
()
.
anyMatch
(
url
->
pathMatcher
.
match
(
url
,
request
.
getRequestURI
()));
return
match
?
null
:
super
.
extract
(
request
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuDaoAuthenticationProvider.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.extra.spring.SpringUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.WebUtils
;
import
com.yifu.cloud.plus.v1.yifu.common.security.service.YifuUserDetailsService
;
import
org.springframework.core.Ordered
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.authentication.InternalAuthenticationServiceException
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsPasswordService
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.security.crypto.factory.PasswordEncoderFactories
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.util.Assert
;
import
java.util.Comparator
;
import
java.util.Map
;
import
java.util.Optional
;
/**
* @author lengleng
* @date 2022/1/15
*/
public
class
YifuDaoAuthenticationProvider
extends
AbstractUserDetailsAuthenticationProvider
{
/**
* The plaintext password used to perform PasswordEncoder#matches(CharSequence,
* String)} on when the user is not found to avoid SEC-2056.
*/
private
static
final
String
USER_NOT_FOUND_PASSWORD
=
"userNotFoundPassword"
;
private
PasswordEncoder
passwordEncoder
;
/**
* The password used to perform {@link PasswordEncoder#matches(CharSequence, String)}
* on when the user is not found to avoid SEC-2056. This is necessary, because some
* {@link PasswordEncoder} implementations will short circuit if the password is not
* in a valid format.
*/
private
volatile
String
userNotFoundEncodedPassword
;
private
UserDetailsService
userDetailsService
;
private
UserDetailsPasswordService
userDetailsPasswordService
;
public
YifuDaoAuthenticationProvider
()
{
setPasswordEncoder
(
PasswordEncoderFactories
.
createDelegatingPasswordEncoder
());
}
@Override
@SuppressWarnings
(
"deprecation"
)
protected
void
additionalAuthenticationChecks
(
UserDetails
userDetails
,
UsernamePasswordAuthenticationToken
authentication
)
throws
AuthenticationException
{
if
(
authentication
.
getCredentials
()
==
null
)
{
this
.
logger
.
debug
(
"Failed to authenticate since no credentials provided"
);
throw
new
BadCredentialsException
(
this
.
messages
.
getMessage
(
"AbstractUserDetailsAuthenticationProvider.badCredentials"
,
"Bad credentials"
));
}
String
presentedPassword
=
authentication
.
getCredentials
().
toString
();
if
(!
this
.
passwordEncoder
.
matches
(
presentedPassword
,
userDetails
.
getPassword
()))
{
this
.
logger
.
debug
(
"Failed to authenticate since password does not match stored value"
);
throw
new
BadCredentialsException
(
this
.
messages
.
getMessage
(
"AbstractUserDetailsAuthenticationProvider.badCredentials"
,
"Bad credentials"
));
}
}
@Override
protected
final
UserDetails
retrieveUser
(
String
username
,
UsernamePasswordAuthenticationToken
authentication
)
throws
AuthenticationException
{
prepareTimingAttackProtection
();
// 此处已获得 客户端认证 获取对应 userDetailsService
Authentication
clientAuthentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
// SSO NPE 处理
String
clientId
;
if
(
clientAuthentication
==
null
)
{
clientId
=
WebUtils
.
getRequest
().
get
().
getParameter
(
"clientId"
);
}
else
{
clientId
=
clientAuthentication
.
getName
();
}
Map
<
String
,
YifuUserDetailsService
>
userDetailsServiceMap
=
SpringUtil
.
getBeansOfType
(
YifuUserDetailsService
.
class
);
Optional
<
YifuUserDetailsService
>
optional
=
userDetailsServiceMap
.
values
().
stream
()
.
filter
(
service
->
service
.
support
(
clientId
,
null
)).
max
(
Comparator
.
comparingInt
(
Ordered:
:
getOrder
));
if
(!
optional
.
isPresent
())
{
throw
new
InternalAuthenticationServiceException
(
"UserDetailsService error , not register"
);
}
try
{
UserDetails
loadedUser
=
optional
.
get
().
loadUserByUsername
(
username
);
if
(
loadedUser
==
null
)
{
throw
new
InternalAuthenticationServiceException
(
"UserDetailsService returned null, which is an interface contract violation"
);
}
return
loadedUser
;
}
catch
(
UsernameNotFoundException
ex
)
{
mitigateAgainstTimingAttack
(
authentication
);
throw
ex
;
}
catch
(
InternalAuthenticationServiceException
ex
)
{
throw
ex
;
}
catch
(
Exception
ex
)
{
throw
new
InternalAuthenticationServiceException
(
ex
.
getMessage
(),
ex
);
}
}
@Override
protected
Authentication
createSuccessAuthentication
(
Object
principal
,
Authentication
authentication
,
UserDetails
user
)
{
boolean
upgradeEncoding
=
this
.
userDetailsPasswordService
!=
null
&&
this
.
passwordEncoder
.
upgradeEncoding
(
user
.
getPassword
());
if
(
upgradeEncoding
)
{
String
presentedPassword
=
authentication
.
getCredentials
().
toString
();
String
newPassword
=
this
.
passwordEncoder
.
encode
(
presentedPassword
);
user
=
this
.
userDetailsPasswordService
.
updatePassword
(
user
,
newPassword
);
}
return
super
.
createSuccessAuthentication
(
principal
,
authentication
,
user
);
}
private
void
prepareTimingAttackProtection
()
{
if
(
this
.
userNotFoundEncodedPassword
==
null
)
{
this
.
userNotFoundEncodedPassword
=
this
.
passwordEncoder
.
encode
(
USER_NOT_FOUND_PASSWORD
);
}
}
private
void
mitigateAgainstTimingAttack
(
UsernamePasswordAuthenticationToken
authentication
)
{
if
(
authentication
.
getCredentials
()
!=
null
)
{
String
presentedPassword
=
authentication
.
getCredentials
().
toString
();
this
.
passwordEncoder
.
matches
(
presentedPassword
,
this
.
userNotFoundEncodedPassword
);
}
}
/**
* Sets the PasswordEncoder instance to be used to encode and validate passwords. If
* not set, the password will be compared using
* {@link PasswordEncoderFactories#createDelegatingPasswordEncoder()}
* @param passwordEncoder must be an instance of one of the {@code PasswordEncoder}
* types.
*/
public
void
setPasswordEncoder
(
PasswordEncoder
passwordEncoder
)
{
Assert
.
notNull
(
passwordEncoder
,
"passwordEncoder cannot be null"
);
this
.
passwordEncoder
=
passwordEncoder
;
this
.
userNotFoundEncodedPassword
=
null
;
}
protected
PasswordEncoder
getPasswordEncoder
()
{
return
this
.
passwordEncoder
;
}
public
void
setUserDetailsService
(
UserDetailsService
userDetailsService
)
{
this
.
userDetailsService
=
userDetailsService
;
}
protected
UserDetailsService
getUserDetailsService
()
{
return
this
.
userDetailsService
;
}
public
void
setUserDetailsPasswordService
(
UserDetailsPasswordService
userDetailsPasswordService
)
{
this
.
userDetailsPasswordService
=
userDetailsPasswordService
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuLocalResourceServerTokenServices.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.extra.spring.SpringUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
com.yifu.cloud.plus.v1.yifu.common.security.exception.UnauthorizedException
;
import
com.yifu.cloud.plus.v1.yifu.common.security.service.YifuUserDetailsService
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.core.Ordered
;
import
org.springframework.security.authentication.InternalAuthenticationServiceException
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
import
org.springframework.security.oauth2.common.exceptions.InvalidTokenException
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.security.oauth2.provider.OAuth2Request
;
import
org.springframework.security.oauth2.provider.token.ResourceServerTokenServices
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
import
java.util.Comparator
;
import
java.util.Map
;
import
java.util.Optional
;
/**
* @author lengleng
* @date 2020/9/29
*/
@RequiredArgsConstructor
public
class
YifuLocalResourceServerTokenServices
implements
ResourceServerTokenServices
{
private
final
TokenStore
tokenStore
;
@Override
public
OAuth2Authentication
loadAuthentication
(
String
accessToken
)
throws
AuthenticationException
,
InvalidTokenException
{
OAuth2Authentication
oAuth2Authentication
=
tokenStore
.
readAuthentication
(
accessToken
);
if
(
oAuth2Authentication
==
null
)
{
return
null
;
}
OAuth2Request
oAuth2Request
=
oAuth2Authentication
.
getOAuth2Request
();
if
(!(
oAuth2Authentication
.
getPrincipal
()
instanceof
YifuUser
))
{
return
oAuth2Authentication
;
}
String
clientId
=
oAuth2Request
.
getClientId
();
Map
<
String
,
YifuUserDetailsService
>
userDetailsServiceMap
=
SpringUtil
.
getBeansOfType
(
YifuUserDetailsService
.
class
);
Optional
<
YifuUserDetailsService
>
optional
=
userDetailsServiceMap
.
values
().
stream
()
.
filter
(
service
->
service
.
support
(
clientId
,
oAuth2Request
.
getGrantType
()))
.
max
(
Comparator
.
comparingInt
(
Ordered:
:
getOrder
));
if
(!
optional
.
isPresent
())
{
throw
new
InternalAuthenticationServiceException
(
"UserDetailsService error , not register"
);
}
// 根据 username 查询 spring cache 最新的值 并返回
YifuUser
yifuUser
=
(
YifuUser
)
oAuth2Authentication
.
getPrincipal
();
UserDetails
userDetails
;
try
{
userDetails
=
optional
.
get
().
loadUserByUser
(
yifuUser
);
}
catch
(
UsernameNotFoundException
notFoundException
)
{
throw
new
UnauthorizedException
(
String
.
format
(
"%s username not found"
,
yifuUser
.
getUsername
()),
notFoundException
);
}
Authentication
userAuthentication
=
new
UsernamePasswordAuthenticationToken
(
userDetails
,
"N/A"
,
userDetails
.
getAuthorities
());
OAuth2Authentication
authentication
=
new
OAuth2Authentication
(
oAuth2Request
,
userAuthentication
);
authentication
.
setAuthenticated
(
true
);
return
authentication
;
}
@Override
public
OAuth2AccessToken
readAccessToken
(
String
accessToken
)
{
throw
new
UnsupportedOperationException
(
"Not supported: read access token"
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuRedisTokenStore.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
org.springframework.data.redis.connection.RedisConnection
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.connection.RedisZSetCommands
;
import
org.springframework.data.redis.core.Cursor
;
import
org.springframework.data.redis.core.ScanOptions
;
import
org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
import
org.springframework.security.oauth2.common.OAuth2RefreshToken
;
import
org.springframework.security.oauth2.provider.OAuth2Authentication
;
import
org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator
;
import
org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
import
org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy
;
import
org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore
;
import
org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ReflectionUtils
;
import
java.lang.reflect.Method
;
import
java.util.*
;
/**
* @author efenderbosch
* @date 2020/9/30
* <p>
* @link https://github.com/spring-projects/spring-security-oauth/pull/1660
* 重写RedisTokenStore ,主要解决 #1814 oauth2中client_id_to_access数据膨胀问题
*/
public
class
YifuRedisTokenStore
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
REFRESH
=
"refresh:"
;
private
static
final
String
REFRESH_TO_ACCESS
=
"refresh_to_access:"
;
private
static
final
String
CLIENT_ID_TO_ACCESS
=
"client_id_to_access_z:"
;
private
static
final
String
UNAME_TO_ACCESS
=
"uname_to_access_z:"
;
private
static
final
boolean
springDataRedis_2_0
=
ClassUtils
.
isPresent
(
"org.springframework.data.redis.connection.RedisStandaloneConfiguration"
,
RedisTokenStore
.
class
.
getClassLoader
());
private
final
RedisConnectionFactory
connectionFactory
;
private
AuthenticationKeyGenerator
authenticationKeyGenerator
=
new
DefaultAuthenticationKeyGenerator
();
private
RedisTokenStoreSerializationStrategy
serializationStrategy
=
new
JdkSerializationStrategy
();
private
String
prefix
=
""
;
private
Method
redisConnectionSet_2_0
;
public
YifuRedisTokenStore
(
RedisConnectionFactory
connectionFactory
)
{
this
.
connectionFactory
=
connectionFactory
;
if
(
springDataRedis_2_0
)
{
this
.
loadRedisConnectionMethods_2_0
();
}
}
public
void
setAuthenticationKeyGenerator
(
AuthenticationKeyGenerator
authenticationKeyGenerator
)
{
this
.
authenticationKeyGenerator
=
authenticationKeyGenerator
;
}
public
void
setSerializationStrategy
(
RedisTokenStoreSerializationStrategy
serializationStrategy
)
{
this
.
serializationStrategy
=
serializationStrategy
;
}
public
void
setPrefix
(
String
prefix
)
{
this
.
prefix
=
prefix
;
}
private
void
loadRedisConnectionMethods_2_0
()
{
this
.
redisConnectionSet_2_0
=
ReflectionUtils
.
findMethod
(
RedisConnection
.
class
,
"set"
,
byte
[].
class
,
byte
[].
class
);
}
private
RedisConnection
getConnection
()
{
return
connectionFactory
.
getConnection
();
}
private
byte
[]
serialize
(
Object
object
)
{
return
serializationStrategy
.
serialize
(
object
);
}
private
byte
[]
serializeKey
(
String
object
)
{
return
serialize
(
prefix
+
object
);
}
private
OAuth2AccessToken
deserializeAccessToken
(
byte
[]
bytes
)
{
return
serializationStrategy
.
deserialize
(
bytes
,
OAuth2AccessToken
.
class
);
}
private
OAuth2Authentication
deserializeAuthentication
(
byte
[]
bytes
)
{
return
serializationStrategy
.
deserialize
(
bytes
,
OAuth2Authentication
.
class
);
}
private
OAuth2RefreshToken
deserializeRefreshToken
(
byte
[]
bytes
)
{
return
serializationStrategy
.
deserialize
(
bytes
,
OAuth2RefreshToken
.
class
);
}
private
byte
[]
serialize
(
String
string
)
{
return
serializationStrategy
.
serialize
(
string
);
}
private
String
deserializeString
(
byte
[]
bytes
)
{
return
serializationStrategy
.
deserializeString
(
bytes
);
}
@Override
public
OAuth2AccessToken
getAccessToken
(
OAuth2Authentication
authentication
)
{
String
key
=
authenticationKeyGenerator
.
extractKey
(
authentication
);
byte
[]
serializedKey
=
serializeKey
(
AUTH_TO_ACCESS
+
key
);
byte
[]
bytes
;
try
(
RedisConnection
conn
=
getConnection
())
{
bytes
=
conn
.
get
(
serializedKey
);
}
OAuth2AccessToken
accessToken
=
deserializeAccessToken
(
bytes
);
if
(
accessToken
!=
null
)
{
OAuth2Authentication
storedAuthentication
=
readAuthentication
(
accessToken
.
getValue
());
if
((
storedAuthentication
==
null
||
!
key
.
equals
(
authenticationKeyGenerator
.
extractKey
(
storedAuthentication
))))
{
// Keep the stores consistent (maybe the same user is
// represented by this authentication but the details have
// changed)
storeAccessToken
(
accessToken
,
authentication
);
}
}
return
accessToken
;
}
@Override
public
OAuth2Authentication
readAuthentication
(
OAuth2AccessToken
token
)
{
return
readAuthentication
(
token
.
getValue
());
}
@Override
public
OAuth2Authentication
readAuthentication
(
String
token
)
{
byte
[]
bytes
;
try
(
RedisConnection
conn
=
getConnection
())
{
bytes
=
conn
.
get
(
serializeKey
(
AUTH
+
token
));
}
return
deserializeAuthentication
(
bytes
);
}
@Override
public
OAuth2Authentication
readAuthenticationForRefreshToken
(
OAuth2RefreshToken
token
)
{
return
readAuthenticationForRefreshToken
(
token
.
getValue
());
}
public
OAuth2Authentication
readAuthenticationForRefreshToken
(
String
token
)
{
try
(
RedisConnection
conn
=
getConnection
())
{
byte
[]
bytes
=
conn
.
get
(
serializeKey
(
REFRESH_AUTH
+
token
));
return
deserializeAuthentication
(
bytes
);
}
}
@Override
public
void
storeAccessToken
(
OAuth2AccessToken
token
,
OAuth2Authentication
authentication
)
{
byte
[]
serializedAccessToken
=
serialize
(
token
);
byte
[]
serializedAuth
=
serialize
(
authentication
);
byte
[]
accessKey
=
serializeKey
(
ACCESS
+
token
.
getValue
());
byte
[]
authKey
=
serializeKey
(
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
());
try
(
RedisConnection
conn
=
getConnection
())
{
conn
.
openPipeline
();
if
(
springDataRedis_2_0
)
{
try
{
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
accessKey
,
serializedAccessToken
);
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
authKey
,
serializedAuth
);
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
authToAccessKey
,
serializedAccessToken
);
}
catch
(
Exception
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
else
{
conn
.
set
(
accessKey
,
serializedAccessToken
);
conn
.
set
(
authKey
,
serializedAuth
);
conn
.
set
(
authToAccessKey
,
serializedAccessToken
);
}
if
(
token
.
getExpiration
()
!=
null
)
{
int
seconds
=
token
.
getExpiresIn
();
long
expirationTime
=
token
.
getExpiration
().
getTime
();
if
(!
authentication
.
isClientOnly
())
{
conn
.
zAdd
(
approvalKey
,
expirationTime
,
serializedAccessToken
);
}
conn
.
zAdd
(
clientId
,
expirationTime
,
serializedAccessToken
);
conn
.
expire
(
accessKey
,
seconds
);
conn
.
expire
(
authKey
,
seconds
);
conn
.
expire
(
authToAccessKey
,
seconds
);
conn
.
expire
(
clientId
,
seconds
);
conn
.
expire
(
approvalKey
,
seconds
);
}
else
{
conn
.
zAdd
(
clientId
,
-
1
,
serializedAccessToken
);
if
(!
authentication
.
isClientOnly
())
{
conn
.
zAdd
(
approvalKey
,
-
1
,
serializedAccessToken
);
}
}
OAuth2RefreshToken
refreshToken
=
token
.
getRefreshToken
();
if
(
refreshToken
!=
null
&&
refreshToken
.
getValue
()
!=
null
)
{
byte
[]
auth
=
serialize
(
token
.
getValue
());
byte
[]
refreshToAccessKey
=
serializeKey
(
REFRESH_TO_ACCESS
+
token
.
getRefreshToken
().
getValue
());
if
(
springDataRedis_2_0
)
{
try
{
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
refreshToAccessKey
,
auth
);
}
catch
(
Exception
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
else
{
conn
.
set
(
refreshToAccessKey
,
auth
);
}
if
(
refreshToken
instanceof
ExpiringOAuth2RefreshToken
)
{
ExpiringOAuth2RefreshToken
expiringRefreshToken
=
(
ExpiringOAuth2RefreshToken
)
refreshToken
;
Date
expiration
=
expiringRefreshToken
.
getExpiration
();
if
(
expiration
!=
null
)
{
int
seconds
=
Long
.
valueOf
((
expiration
.
getTime
()
-
System
.
currentTimeMillis
())
/
1000L
)
.
intValue
();
conn
.
expire
(
refreshToAccessKey
,
seconds
);
}
}
}
conn
.
closePipeline
();
}
}
private
static
String
getApprovalKey
(
OAuth2Authentication
authentication
)
{
String
userName
=
authentication
.
getUserAuthentication
()
==
null
?
""
:
authentication
.
getUserAuthentication
().
getName
();
return
getApprovalKey
(
authentication
.
getOAuth2Request
().
getClientId
(),
userName
);
}
private
static
String
getApprovalKey
(
String
clientId
,
String
userName
)
{
return
clientId
+
(
userName
==
null
?
""
:
":"
+
userName
);
}
@Override
public
void
removeAccessToken
(
OAuth2AccessToken
accessToken
)
{
removeAccessToken
(
accessToken
.
getValue
());
}
@Override
public
OAuth2AccessToken
readAccessToken
(
String
tokenValue
)
{
byte
[]
key
=
serializeKey
(
ACCESS
+
tokenValue
);
byte
[]
bytes
;
try
(
RedisConnection
conn
=
getConnection
())
{
bytes
=
conn
.
get
(
key
);
}
return
deserializeAccessToken
(
bytes
);
}
public
void
removeAccessToken
(
String
tokenValue
)
{
byte
[]
accessKey
=
serializeKey
(
ACCESS
+
tokenValue
);
byte
[]
authKey
=
serializeKey
(
AUTH
+
tokenValue
);
try
(
RedisConnection
conn
=
getConnection
())
{
conn
.
openPipeline
();
conn
.
get
(
accessKey
);
conn
.
get
(
authKey
);
conn
.
del
(
accessKey
);
// Don't remove the refresh token - it's up to the caller to do that
conn
.
del
(
authKey
);
List
<
Object
>
results
=
conn
.
closePipeline
();
byte
[]
access
=
(
byte
[])
results
.
get
(
0
);
byte
[]
auth
=
(
byte
[])
results
.
get
(
1
);
OAuth2Authentication
authentication
=
deserializeAuthentication
(
auth
);
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
());
conn
.
openPipeline
();
conn
.
del
(
authToAccessKey
);
conn
.
zRem
(
unameKey
,
access
);
conn
.
zRem
(
clientId
,
access
);
conn
.
del
(
serialize
(
ACCESS
+
key
));
conn
.
closePipeline
();
}
}
}
@Override
public
void
storeRefreshToken
(
OAuth2RefreshToken
refreshToken
,
OAuth2Authentication
authentication
)
{
byte
[]
refreshKey
=
serializeKey
(
REFRESH
+
refreshToken
.
getValue
());
byte
[]
refreshAuthKey
=
serializeKey
(
REFRESH_AUTH
+
refreshToken
.
getValue
());
byte
[]
serializedRefreshToken
=
serialize
(
refreshToken
);
try
(
RedisConnection
conn
=
getConnection
())
{
conn
.
openPipeline
();
if
(
springDataRedis_2_0
)
{
try
{
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
refreshKey
,
serializedRefreshToken
);
this
.
redisConnectionSet_2_0
.
invoke
(
conn
,
refreshAuthKey
,
serialize
(
authentication
));
}
catch
(
Exception
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
else
{
conn
.
set
(
refreshKey
,
serializedRefreshToken
);
conn
.
set
(
refreshAuthKey
,
serialize
(
authentication
));
}
if
(
refreshToken
instanceof
ExpiringOAuth2RefreshToken
)
{
ExpiringOAuth2RefreshToken
expiringRefreshToken
=
(
ExpiringOAuth2RefreshToken
)
refreshToken
;
Date
expiration
=
expiringRefreshToken
.
getExpiration
();
if
(
expiration
!=
null
)
{
int
seconds
=
Long
.
valueOf
((
expiration
.
getTime
()
-
System
.
currentTimeMillis
())
/
1000L
).
intValue
();
conn
.
expire
(
refreshKey
,
seconds
);
conn
.
expire
(
refreshAuthKey
,
seconds
);
}
}
conn
.
closePipeline
();
}
}
@Override
public
OAuth2RefreshToken
readRefreshToken
(
String
tokenValue
)
{
byte
[]
key
=
serializeKey
(
REFRESH
+
tokenValue
);
byte
[]
bytes
;
try
(
RedisConnection
conn
=
getConnection
())
{
bytes
=
conn
.
get
(
key
);
}
return
deserializeRefreshToken
(
bytes
);
}
@Override
public
void
removeRefreshToken
(
OAuth2RefreshToken
refreshToken
)
{
removeRefreshToken
(
refreshToken
.
getValue
());
}
public
void
removeRefreshToken
(
String
tokenValue
)
{
byte
[]
refreshKey
=
serializeKey
(
REFRESH
+
tokenValue
);
byte
[]
refreshAuthKey
=
serializeKey
(
REFRESH_AUTH
+
tokenValue
);
byte
[]
refresh2AccessKey
=
serializeKey
(
REFRESH_TO_ACCESS
+
tokenValue
);
try
(
RedisConnection
conn
=
getConnection
())
{
conn
.
openPipeline
();
conn
.
del
(
refreshKey
);
conn
.
del
(
refreshAuthKey
);
conn
.
del
(
refresh2AccessKey
);
conn
.
closePipeline
();
}
}
@Override
public
void
removeAccessTokenUsingRefreshToken
(
OAuth2RefreshToken
refreshToken
)
{
removeAccessTokenUsingRefreshToken
(
refreshToken
.
getValue
());
}
private
void
removeAccessTokenUsingRefreshToken
(
String
refreshToken
)
{
byte
[]
key
=
serializeKey
(
REFRESH_TO_ACCESS
+
refreshToken
);
List
<
Object
>
results
;
try
(
RedisConnection
conn
=
getConnection
())
{
conn
.
openPipeline
();
conn
.
get
(
key
);
conn
.
del
(
key
);
results
=
conn
.
closePipeline
();
}
byte
[]
bytes
=
(
byte
[])
results
.
get
(
0
);
String
accessToken
=
deserializeString
(
bytes
);
if
(
accessToken
!=
null
)
{
removeAccessToken
(
accessToken
);
}
}
private
List
<
byte
[]>
getZByteLists
(
byte
[]
key
,
RedisConnection
conn
)
{
// Sorted Set expiration maintenance
long
currentTime
=
System
.
currentTimeMillis
();
conn
.
zRemRangeByScore
(
key
,
0
,
currentTime
);
List
<
byte
[]>
byteList
;
Long
size
=
conn
.
zCard
(
key
);
assert
size
!=
null
;
byteList
=
new
ArrayList
<>(
size
.
intValue
());
Cursor
<
RedisZSetCommands
.
Tuple
>
cursor
=
conn
.
zScan
(
key
,
ScanOptions
.
NONE
);
while
(
cursor
.
hasNext
())
{
RedisZSetCommands
.
Tuple
t
=
cursor
.
next
();
// Probably not necessary because of the maintenance at the beginning but why
// not...
if
(
t
.
getScore
()
==
-
1
||
t
.
getScore
()
>
currentTime
)
{
byteList
.
add
(
t
.
getValue
());
}
}
return
byteList
;
}
/**
* Runs a maintenance of the RedisTokenStore.
* <p>
* SortedSets UNAME_TO_ACCESS and CLIENT_ID_TO_ACCESS contains access tokens that can
* expire. This expiration is set as a score of the Redis SortedSet data structure.
* Redis does not support expiration of items in a container data structure. It
* supports only expiration of whole key. In case there is still new access tokens
* being stored into the RedisTokenStore before whole key gets expired, the expiration
* is prolonged and the key is not effectively deleted. To do "garbage collection"
* this method should be called once upon a time.
* @return how many items were removed
*/
public
long
doMaintenance
()
{
long
removed
=
0
;
try
(
RedisConnection
conn
=
getConnection
())
{
// client_id_to_acccess maintenance
Cursor
<
byte
[]>
clientToAccessKeys
=
conn
.
scan
(
ScanOptions
.
scanOptions
().
match
(
prefix
+
CLIENT_ID_TO_ACCESS
+
"*"
).
build
());
while
(
clientToAccessKeys
.
hasNext
())
{
byte
[]
clientIdToAccessKey
=
clientToAccessKeys
.
next
();
removed
+=
conn
.
zRemRangeByScore
(
clientIdToAccessKey
,
0
,
System
.
currentTimeMillis
());
}
// uname_to_access maintenance
Cursor
<
byte
[]>
unameToAccessKeys
=
conn
.
scan
(
ScanOptions
.
scanOptions
().
match
(
prefix
+
UNAME_TO_ACCESS
+
"*"
).
build
());
while
(
unameToAccessKeys
.
hasNext
())
{
byte
[]
unameToAccessKey
=
unameToAccessKeys
.
next
();
removed
+=
conn
.
zRemRangeByScore
(
unameToAccessKey
,
0
,
System
.
currentTimeMillis
());
}
}
return
removed
;
}
@Override
public
Collection
<
OAuth2AccessToken
>
findTokensByClientIdAndUserName
(
String
clientId
,
String
userName
)
{
byte
[]
approvalKey
=
serializeKey
(
UNAME_TO_ACCESS
+
getApprovalKey
(
clientId
,
userName
));
List
<
byte
[]>
byteList
;
try
(
RedisConnection
conn
=
getConnection
())
{
byteList
=
getZByteLists
(
approvalKey
,
conn
);
}
if
(
byteList
.
size
()
==
0
)
{
return
Collections
.
emptySet
();
}
List
<
OAuth2AccessToken
>
accessTokens
=
new
ArrayList
<>(
byteList
.
size
());
for
(
byte
[]
bytes
:
byteList
)
{
OAuth2AccessToken
accessToken
=
deserializeAccessToken
(
bytes
);
accessTokens
.
add
(
accessToken
);
}
return
Collections
.
unmodifiableCollection
(
accessTokens
);
}
@Override
public
Collection
<
OAuth2AccessToken
>
findTokensByClientId
(
String
clientId
)
{
byte
[]
key
=
serializeKey
(
CLIENT_ID_TO_ACCESS
+
clientId
);
List
<
byte
[]>
byteList
;
try
(
RedisConnection
conn
=
getConnection
())
{
byteList
=
getZByteLists
(
key
,
conn
);
}
if
(
byteList
.
size
()
==
0
)
{
return
Collections
.
emptySet
();
}
List
<
OAuth2AccessToken
>
accessTokens
=
new
ArrayList
<>(
byteList
.
size
());
for
(
byte
[]
bytes
:
byteList
)
{
OAuth2AccessToken
accessToken
=
deserializeAccessToken
(
bytes
);
accessTokens
.
add
(
accessToken
);
}
return
Collections
.
unmodifiableCollection
(
accessTokens
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuResourceServerAutoConfiguration.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.security.oauth2.provider.token.ResourceServerTokenServices
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
/**
* @author lengleng
* @date 2020-06-23
*/
@EnableConfigurationProperties
(
PermitAllUrlProperties
.
class
)
public
class
YifuResourceServerAutoConfiguration
{
@Bean
(
"pms"
)
public
PermissionService
permissionService
()
{
return
new
PermissionService
();
}
@Bean
public
YifuBearerTokenExtractor
yifuBearerTokenExtractor
(
PermitAllUrlProperties
urlProperties
)
{
return
new
YifuBearerTokenExtractor
(
urlProperties
);
}
@Bean
public
ResourceAuthExceptionEntryPoint
resourceAuthExceptionEntryPoint
(
ObjectMapper
objectMapper
)
{
return
new
ResourceAuthExceptionEntryPoint
(
objectMapper
);
}
@Bean
@Primary
public
ResourceServerTokenServices
resourceServerTokenServices
(
TokenStore
tokenStore
)
{
return
new
YifuLocalResourceServerTokenServices
(
tokenStore
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuResourceServerConfigurerAdapter.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
;
import
org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter
;
import
org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer
;
import
org.springframework.security.oauth2.provider.token.RemoteTokenServices
;
import
org.springframework.security.oauth2.provider.token.ResourceServerTokenServices
;
/**
* @author lengleng
* @date 2019/03/08
*
* <p>
* 1. 支持remoteTokenServices 负载均衡 2. 支持 获取用户全部信息 3. 接口对外暴露,不校验 Authentication Header 头
*/
@Slf4j
public
class
YifuResourceServerConfigurerAdapter
extends
ResourceServerConfigurerAdapter
{
@Autowired
protected
ResourceAuthExceptionEntryPoint
resourceAuthExceptionEntryPoint
;
@Autowired
protected
RemoteTokenServices
remoteTokenServices
;
@Autowired
private
PermitAllUrlProperties
permitAllUrl
;
@Autowired
private
YifuBearerTokenExtractor
yifuBearerTokenExtractor
;
@Autowired
private
ResourceServerTokenServices
resourceServerTokenServices
;
/**
* 默认的配置,对外暴露
* @param httpSecurity
*/
@Override
@SneakyThrows
public
void
configure
(
HttpSecurity
httpSecurity
)
{
// 允许使用iframe 嵌套,避免swagger-ui 不被加载的问题
httpSecurity
.
headers
().
frameOptions
().
disable
();
ExpressionUrlAuthorizationConfigurer
<
HttpSecurity
>.
ExpressionInterceptUrlRegistry
registry
=
httpSecurity
.
authorizeRequests
();
permitAllUrl
.
getUrls
().
forEach
(
url
->
registry
.
antMatchers
(
url
).
permitAll
());
// “/user/getInfoByUsername" URL 访问放行
registry
.
and
()
.
authorizeRequests
().
antMatchers
(
"/user/getInfoByUsername"
,
"/api/**"
,
"/api-docs/**"
).
permitAll
()
.
anyRequest
().
authenticated
().
and
().
csrf
().
disable
();
}
@Override
public
void
configure
(
ResourceServerSecurityConfigurer
resources
)
{
resources
.
authenticationEntryPoint
(
resourceAuthExceptionEntryPoint
).
tokenExtractor
(
yifuBearerTokenExtractor
)
.
tokenServices
(
resourceServerTokenServices
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuResourceServerTokenRelayAutoConfiguration.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.condition.AllNestedConditions
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration
;
import
org.springframework.cloud.commons.security.AccessTokenContextRelay
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Conditional
;
import
org.springframework.security.oauth2.client.OAuth2ClientContext
;
import
org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration
;
import
org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration
;
import
java.lang.annotation.*
;
/**
* @author lengleng
* @date 2019/2/1 注入AccessTokenContextRelay 解决feign 传递token 为空问题
*/
@AutoConfigureAfter
(
OAuth2AutoConfiguration
.
class
)
@ConditionalOnWebApplication
@ConditionalOnProperty
(
"security.oauth2.client.client-id"
)
public
class
YifuResourceServerTokenRelayAutoConfiguration
{
@Bean
public
AccessTokenContextRelay
accessTokenContextRelay
(
OAuth2ClientContext
context
)
{
return
new
AccessTokenContextRelay
(
context
);
}
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Conditional
(
OAuth2OnClientInResourceServerCondition
.
class
)
@interface
ConditionalOnOAuth2ClientInResourceServer
{
}
private
static
class
OAuth2OnClientInResourceServerCondition
extends
AllNestedConditions
{
public
OAuth2OnClientInResourceServerCondition
()
{
super
(
ConfigurationPhase
.
REGISTER_BEAN
);
}
@ConditionalOnBean
(
ResourceServerConfiguration
.
class
)
static
class
Server
{
}
@ConditionalOnBean
(
OAuth2ClientConfiguration
.
class
)
static
class
Client
{
}
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuSecurityBeanDefinitionRegistrar.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.GenericBeanDefinition
;
import
org.springframework.context.annotation.ImportBeanDefinitionRegistrar
;
import
org.springframework.core.type.AnnotationMetadata
;
/**
* @author lengleng
* @date 2019/03/08
*/
@Slf4j
public
class
YifuSecurityBeanDefinitionRegistrar
implements
ImportBeanDefinitionRegistrar
{
/**
* 根据注解值动态注入资源服务器的相关属性
* @param metadata 注解信息
* @param registry 注册器
*/
@Override
public
void
registerBeanDefinitions
(
AnnotationMetadata
metadata
,
BeanDefinitionRegistry
registry
)
{
if
(
registry
.
isBeanNameInUse
(
SecurityConstants
.
RESOURCE_SERVER_CONFIGURER
))
{
log
.
warn
(
"本地存在资源服务器配置,覆盖默认配置:"
+
SecurityConstants
.
RESOURCE_SERVER_CONFIGURER
);
return
;
}
GenericBeanDefinition
beanDefinition
=
new
GenericBeanDefinition
();
beanDefinition
.
setBeanClass
(
YifuResourceServerConfigurerAdapter
.
class
);
registry
.
registerBeanDefinition
(
SecurityConstants
.
RESOURCE_SERVER_CONFIGURER
,
beanDefinition
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuSecurityInnerAspect.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
cn.hutool.core.util.StrUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.security.annotation.Inner
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.security.access.AccessDeniedException
;
import
javax.servlet.http.HttpServletRequest
;
/**
* @author lengleng
* @date 2019/02/14
* <p>
* 服务间接口不鉴权处理逻辑
*/
@Slf4j
@Aspect
@RequiredArgsConstructor
public
class
YifuSecurityInnerAspect
implements
Ordered
{
private
final
HttpServletRequest
request
;
@SneakyThrows
@Around
(
"@within(inner) || @annotation(inner)"
)
public
Object
around
(
ProceedingJoinPoint
point
,
Inner
inner
)
{
// 实际注入的inner实体由表达式后一个注解决定,即是方法上的@Inner注解实体,若方法上无@Inner注解,则获取类上的
if
(
inner
==
null
)
{
Class
<?>
clazz
=
point
.
getTarget
().
getClass
();
inner
=
AnnotationUtils
.
findAnnotation
(
clazz
,
Inner
.
class
);
}
String
header
=
request
.
getHeader
(
SecurityConstants
.
FROM
);
if
(
inner
.
value
()
&&
!
StrUtil
.
equals
(
SecurityConstants
.
FROM_IN
,
header
))
{
log
.
warn
(
"访问接口 {} 没有权限"
,
point
.
getSignature
().
getName
());
throw
new
AccessDeniedException
(
"Access is denied"
);
}
return
point
.
proceed
();
}
@Override
public
int
getOrder
()
{
return
Ordered
.
HIGHEST_PRECEDENCE
+
1
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuSecurityMessageSourceConfiguration.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.context.MessageSource
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.support.ReloadableResourceBundleMessageSource
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
import
static
org
.
springframework
.
boot
.
autoconfigure
.
condition
.
ConditionalOnWebApplication
.
Type
.
SERVLET
;
/**
* @author lengleng
* @date 2022年01月06日
* <p>
* 注入自定义错误处理
*/
@ConditionalOnWebApplication
(
type
=
SERVLET
)
public
class
YifuSecurityMessageSourceConfiguration
implements
WebMvcConfigurer
{
@Bean
public
MessageSource
securityMessageSource
()
{
ReloadableResourceBundleMessageSource
messageSource
=
new
ReloadableResourceBundleMessageSource
();
messageSource
.
addBasenames
(
"classpath:org/springframework/security/messages"
);
return
messageSource
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuTokenStoreAutoCleanSchedule.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.SpringContextHolder
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter
;
/**
* @author lengleng
* @date 2020/9/29
* <p>
* redis token store 自动配置
*/
@Slf4j
@EnableScheduling
@ConditionalOnBean
(
AuthorizationServerConfigurerAdapter
.
class
)
public
class
YifuTokenStoreAutoCleanSchedule
{
/**
* 每小时执行一致,避免 redis zset 容量问题
*/
@Scheduled
(
cron
=
"@hourly"
)
public
void
doMaintenance
()
{
YifuRedisTokenStore
tokenStore
=
SpringContextHolder
.
getBean
(
YifuRedisTokenStore
.
class
);
long
maintenance
=
tokenStore
.
doMaintenance
();
log
.
debug
(
"清理Redis ZADD 过期 token 数量: {}"
,
maintenance
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuTokenStoreAutoConfiguration.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
/**
* @author lengleng
* @date 2021/10/16
*/
public
class
YifuTokenStoreAutoConfiguration
{
@Bean
public
TokenStore
tokenStore
(
RedisConnectionFactory
redisConnectionFactory
)
{
YifuRedisTokenStore
tokenStore
=
new
YifuRedisTokenStore
(
redisConnectionFactory
);
tokenStore
.
setPrefix
(
CacheConstants
.
PROJECT_OAUTH_ACCESS
);
return
tokenStore
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/component/YifuWebResponseExceptionTranslator.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
component
;
import
com.yifu.cloud.plus.v1.yifu.common.security.exception.*
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.security.access.AccessDeniedException
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.oauth2.common.DefaultThrowableAnalyzer
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
import
org.springframework.security.oauth2.common.exceptions.*
;
import
org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator
;
import
org.springframework.security.web.util.ThrowableAnalyzer
;
import
org.springframework.web.HttpRequestMethodNotSupportedException
;
/**
* @author lengleng
* @date 2019/2/1 异常处理,重写oauth 默认实现
*/
@Slf4j
public
class
YifuWebResponseExceptionTranslator
implements
WebResponseExceptionTranslator
{
private
ThrowableAnalyzer
throwableAnalyzer
=
new
DefaultThrowableAnalyzer
();
@Override
@SneakyThrows
public
ResponseEntity
<
OAuth2Exception
>
translate
(
Exception
e
)
{
// Try to extract a SpringSecurityException from the stacktrace
Throwable
[]
causeChain
=
throwableAnalyzer
.
determineCauseChain
(
e
);
Exception
ase
=
(
AuthenticationException
)
throwableAnalyzer
.
getFirstThrowableOfType
(
AuthenticationException
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
(
new
UnauthorizedException
(
e
.
getMessage
(),
e
));
}
ase
=
(
AccessDeniedException
)
throwableAnalyzer
.
getFirstThrowableOfType
(
AccessDeniedException
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
(
new
ForbiddenException
(
ase
.
getMessage
(),
ase
));
}
ase
=
(
InvalidGrantException
)
throwableAnalyzer
.
getFirstThrowableOfType
(
InvalidGrantException
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
(
new
InvalidException
(
ase
.
getMessage
(),
ase
));
}
// token 过期 特殊处理 返回 424 不是 401
ase
=
(
InvalidTokenException
)
throwableAnalyzer
.
getFirstThrowableOfType
(
InvalidTokenException
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
(
new
TokenInvalidException
(
ase
.
getMessage
(),
ase
));
}
ase
=
(
HttpRequestMethodNotSupportedException
)
throwableAnalyzer
.
getFirstThrowableOfType
(
HttpRequestMethodNotSupportedException
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
(
new
MethodNotAllowed
(
ase
.
getMessage
(),
ase
));
}
ase
=
(
OAuth2Exception
)
throwableAnalyzer
.
getFirstThrowableOfType
(
OAuth2Exception
.
class
,
causeChain
);
if
(
ase
!=
null
)
{
return
handleOAuth2Exception
((
OAuth2Exception
)
ase
);
}
return
handleOAuth2Exception
(
new
ServerErrorException
(
HttpStatus
.
INTERNAL_SERVER_ERROR
.
getReasonPhrase
(),
e
));
}
private
ResponseEntity
<
OAuth2Exception
>
handleOAuth2Exception
(
OAuth2Exception
e
)
{
int
status
=
e
.
getHttpErrorCode
();
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
set
(
HttpHeaders
.
CACHE_CONTROL
,
"no-store"
);
headers
.
set
(
HttpHeaders
.
PRAGMA
,
"no-cache"
);
if
(
status
==
HttpStatus
.
UNAUTHORIZED
.
value
()
||
(
e
instanceof
InsufficientScopeException
))
{
headers
.
set
(
HttpHeaders
.
WWW_AUTHENTICATE
,
String
.
format
(
"%s %s"
,
OAuth2AccessToken
.
BEARER_TYPE
,
e
.
getSummary
()));
}
// 客户端异常直接返回客户端,不然无法解析
if
(
e
instanceof
ClientAuthenticationException
)
{
return
new
ResponseEntity
<>(
e
,
headers
,
HttpStatus
.
valueOf
(
status
));
}
return
new
ResponseEntity
<>(
new
YifuAuth2Exception
(
e
.
getMessage
(),
e
.
getOAuth2ErrorCode
()),
headers
,
HttpStatus
.
valueOf
(
status
));
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/DataException.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
/**
* @program: master
* @description: 数据异常
* @author: pwang
* @create: 2019-11-29 11:31
**/
public
class
DataException
extends
Exception
{
private
static
final
long
serialVersionUID
=
-
7285211528095468151L
;
public
DataException
()
{
}
public
DataException
(
String
msg
)
{
super
(
msg
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/ForbiddenException.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
org.springframework.http.HttpStatus
;
/**
* @author lengleng
* @date 2019/2/1
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
ForbiddenException
extends
YifuAuth2Exception
{
public
ForbiddenException
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"access_denied"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
HttpStatus
.
FORBIDDEN
.
value
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/GlobalExceptionHandler.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.exc.InvalidFormatException
;
import
com.yifu.cloud.plus.v1.yifu.common.core.exception.ValidateCodeException
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.Common
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.converter.HttpMessageNotReadableException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.validation.BindException
;
import
org.springframework.validation.FieldError
;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
import
javax.validation.ConstraintViolation
;
import
javax.validation.ConstraintViolationException
;
import
java.util.List
;
import
java.util.Set
;
/**
* 全局的的异常处理器
*/
@Slf4j
@RestControllerAdvice
public
class
GlobalExceptionHandler
{
/**
* description:获取用户账号
*
* @Param: []
* @Return: java.lang.String
* @Author: pwang
* @Date: 2020/7/30
*/
public
String
getUsername
()
{
Authentication
authentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
if
(
authentication
==
null
)
{
return
null
;
}
return
authentication
.
getName
();
}
/**
* 全局异常.
*
* @param e the e
* @return R
* 带有@ResponseStatus注解的异常类会被ResponseStatusExceptionResolver 解析。可以实现自定义的一些异常,同时在页面上进行显示
* @ExceptionHandler:当这个Controller中任何一个方法发生异常,一定会被这个方法拦截到
*/
@ExceptionHandler
(
Exception
.
class
)
@ResponseStatus
(
HttpStatus
.
INTERNAL_SERVER_ERROR
)
@ResponseBody
public
R
exception
(
Exception
e
)
{
errorLog
(
e
);
if
(
null
!=
e
.
getMessage
()){
return
R
.
failed
(
e
.
getMessage
());
}
else
{
return
R
.
failed
(
e
,
"系统异常!"
);
}
}
@ExceptionHandler
({
HttpMessageNotReadableException
.
class
})
@ResponseStatus
(
HttpStatus
.
INTERNAL_SERVER_ERROR
)
public
R
notReadableException
(
Exception
e
)
{
errorLog
(
e
);
if
(
null
!=
e
.
getMessage
()){
return
R
.
failed
(
"数据参数解析异常!"
,
e
.
getMessage
());
}
else
{
return
R
.
failed
(
e
,
"数据参数解析异常!"
);
}
}
@ExceptionHandler
({
NumberFormatException
.
class
,
InvalidFormatException
.
class
})
@ResponseStatus
(
HttpStatus
.
INTERNAL_SERVER_ERROR
)
public
R
formatException
(
Exception
e
)
{
errorLog
(
e
);
if
(
null
!=
e
.
getMessage
()){
return
R
.
failed
(
"数据格转换异常!"
,
e
.
getMessage
());
}
else
{
return
R
.
failed
(
e
,
"数据格转换异常!"
);
}
}
/**
* validation Exception
*
* @param exception
* @return R
*/
@ExceptionHandler
({
MethodArgumentNotValidException
.
class
,
BindException
.
class
,
})
@ResponseStatus
(
HttpStatus
.
BAD_REQUEST
)
public
R
bodyValidExceptionHandler
(
MethodArgumentNotValidException
exception
)
{
List
<
FieldError
>
fieldErrors
=
exception
.
getBindingResult
().
getFieldErrors
();
R
result
=
R
.
failed
(
"数据验证出错:"
.
concat
(
fieldErrors
.
get
(
0
).
getDefaultMessage
()));
errorLog
(
exception
);
return
result
;
}
/**
* validation Exception
*
* @param exception
* @return R
*/
@ExceptionHandler
({
ConstraintViolationException
.
class
})
@ResponseStatus
(
HttpStatus
.
BAD_REQUEST
)
public
R
bodyValidExceptionHandler
(
ConstraintViolationException
exception
)
{
Set
<
ConstraintViolation
<?>>
constraintViolations
=
exception
.
getConstraintViolations
();
String
mess
=
exception
.
getMessage
();
if
(
Common
.
isEmpty
(
constraintViolations
)){
for
(
ConstraintViolation
constraintViolation:
constraintViolations
){
mess
=
constraintViolation
.
getMessage
();
break
;
}
}
R
result
=
R
.
failed
(
"数据验证出错:"
.
concat
(
mess
));
errorLog
(
exception
);
return
result
;
}
/**
* 数据异常 Exception
*
* @param e
* @return R
*/
@ExceptionHandler
({
ValidateCodeException
.
class
,
DataException
.
class
})
@ResponseStatus
(
HttpStatus
.
BAD_REQUEST
)
public
R
dataExceptionHandler
(
Exception
e
)
{
errorLog
(
e
);
R
result
=
R
.
failed
(
"数据异常:"
+
e
.
getMessage
());
return
result
;
}
/**
* 异常打印的方法
* @Author pwang
* @Date 2020-07-30 15:14
* @param exception
* @return
**/
private
void
errorLog
(
Exception
exception
)
{
try
{
log
.
error
(
"全局异常信息 触发用户:{} ex={}"
,
getUsername
(),
exception
.
getMessage
(),
exception
);
}
catch
(
Exception
e
){
log
.
error
(
"全局异常信息 触发用户:获取失败 ex={}"
,
exception
.
getMessage
(),
exception
);
}
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/InvalidException.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
/**
* @author lengleng
* @date 2019/2/1
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
InvalidException
extends
YifuAuth2Exception
{
public
InvalidException
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"invalid_exception"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
426
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/MethodNotAllowed.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
org.springframework.http.HttpStatus
;
/**
* @author lengleng
* @date 2019/2/1
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
MethodNotAllowed
extends
YifuAuth2Exception
{
public
MethodNotAllowed
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"method_not_allowed"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
HttpStatus
.
METHOD_NOT_ALLOWED
.
value
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/ServerErrorException.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
org.springframework.http.HttpStatus
;
/**
* @author lengleng
* @date 2019/2/1
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
ServerErrorException
extends
YifuAuth2Exception
{
public
ServerErrorException
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"server_error"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/TokenInvalidException.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the yifu4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
org.springframework.http.HttpStatus
;
/**
* @author lengleng
* @date 2021-08-05
* <p>
* 令牌不合法
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
TokenInvalidException
extends
YifuAuth2Exception
{
public
TokenInvalidException
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"invalid_token"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
HttpStatus
.
FAILED_DEPENDENCY
.
value
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/UnauthorizedException.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
org.springframework.http.HttpStatus
;
/**
* @author lengleng
* @date 2019/2/1
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
UnauthorizedException
extends
YifuAuth2Exception
{
public
UnauthorizedException
(
String
msg
,
Throwable
t
)
{
super
(
msg
);
}
@Override
public
String
getOAuth2ErrorCode
()
{
return
"unauthorized"
;
}
@Override
public
int
getHttpErrorCode
()
{
return
HttpStatus
.
UNAUTHORIZED
.
value
();
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/exception/YifuAuth2Exception.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
exception
;
import
com.fasterxml.jackson.databind.annotation.JsonSerialize
;
import
com.yifu.cloud.plus.v1.yifu.common.security.component.YifuAuth2ExceptionSerializer
;
import
lombok.Getter
;
import
org.springframework.security.oauth2.common.exceptions.OAuth2Exception
;
/**
* @author lengleng
* @date 2019/2/1 自定义OAuth2Exception
*/
@JsonSerialize
(
using
=
YifuAuth2ExceptionSerializer
.
class
)
public
class
YifuAuth2Exception
extends
OAuth2Exception
{
@Getter
private
String
errorCode
;
public
YifuAuth2Exception
(
String
msg
)
{
super
(
msg
);
}
public
YifuAuth2Exception
(
String
msg
,
String
errorCode
)
{
super
(
msg
);
this
.
errorCode
=
errorCode
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/feign/YifuFeignClientConfiguration.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
feign
;
import
feign.RequestInterceptor
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.cloud.commons.security.AccessTokenContextRelay
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.security.oauth2.client.OAuth2ClientContext
;
import
org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails
;
/**
* @author lengleng
* @date 2019/2/1 feign 拦截器传递 header 中oauth token, 使用hystrix 的信号量模式
*/
@ConditionalOnProperty
(
"security.oauth2.client.client-id"
)
public
class
YifuFeignClientConfiguration
{
@Bean
public
RequestInterceptor
oauth2FeignRequestInterceptor
(
OAuth2ClientContext
oAuth2ClientContext
,
OAuth2ProtectedResourceDetails
resource
,
AccessTokenContextRelay
accessTokenContextRelay
)
{
return
new
YifuFeignClientInterceptor
(
oAuth2ClientContext
,
resource
,
accessTokenContextRelay
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/feign/YifuFeignClientInterceptor.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
feign
;
import
cn.hutool.core.collection.CollUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
feign.RequestTemplate
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.commons.security.AccessTokenContextRelay
;
import
org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor
;
import
org.springframework.security.oauth2.client.OAuth2ClientContext
;
import
org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails
;
import
java.util.Collection
;
/**
* @author lengleng
* @date 2019/2/1 扩展OAuth2FeignRequestInterceptor
*/
@Slf4j
public
class
YifuFeignClientInterceptor
extends
OAuth2FeignRequestInterceptor
{
private
final
OAuth2ClientContext
oAuth2ClientContext
;
private
final
AccessTokenContextRelay
accessTokenContextRelay
;
/**
* Default constructor which uses the provided OAuth2ClientContext and Bearer tokens
* within Authorization header
* @param oAuth2ClientContext provided context
* @param resource type of resource to be accessed
* @param accessTokenContextRelay
*/
public
YifuFeignClientInterceptor
(
OAuth2ClientContext
oAuth2ClientContext
,
OAuth2ProtectedResourceDetails
resource
,
AccessTokenContextRelay
accessTokenContextRelay
)
{
super
(
oAuth2ClientContext
,
resource
);
this
.
oAuth2ClientContext
=
oAuth2ClientContext
;
this
.
accessTokenContextRelay
=
accessTokenContextRelay
;
}
/**
* Create a template with the header of provided name and extracted extract 1. 如果使用
* 非web 请求,header 区别 2. 根据authentication 还原请求token
* @param template
*/
@Override
public
void
apply
(
RequestTemplate
template
)
{
Collection
<
String
>
fromHeader
=
template
.
headers
().
get
(
SecurityConstants
.
FROM
);
if
(
CollUtil
.
isNotEmpty
(
fromHeader
)
&&
fromHeader
.
contains
(
SecurityConstants
.
FROM_IN
))
{
return
;
}
accessTokenContextRelay
.
copyToken
();
if
(
oAuth2ClientContext
!=
null
&&
oAuth2ClientContext
.
getAccessToken
()
!=
null
)
{
super
.
apply
(
template
);
}
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/grant/CustomAppAuthenticationProvider.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
grant
;
import
cn.hutool.extra.spring.SpringUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.security.service.YifuUserDetailsService
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.core.Ordered
;
import
org.springframework.security.authentication.AccountStatusUserDetailsChecker
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.authentication.InternalAuthenticationServiceException
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsChecker
;
import
java.util.Comparator
;
import
java.util.Map
;
import
java.util.Optional
;
/**
* @author hzq
* @since 2021-09-14
*/
@Slf4j
public
class
CustomAppAuthenticationProvider
extends
AbstractUserDetailsAuthenticationProvider
{
/**
* user 属性校验
*/
@Setter
private
UserDetailsChecker
preAuthenticationChecks
=
new
AccountStatusUserDetailsChecker
();
/**
* 校验 请求信息userDetails
* @param userDetails 用户信息
* @param authentication 认证信息
* @throws AuthenticationException
*/
@Override
protected
void
additionalAuthenticationChecks
(
UserDetails
userDetails
,
UsernamePasswordAuthenticationToken
authentication
)
throws
AuthenticationException
{
if
(
authentication
.
getCredentials
()
==
null
)
{
this
.
logger
.
debug
(
"Failed to authenticate since no credentials provided"
);
throw
new
BadCredentialsException
(
this
.
messages
.
getMessage
(
"AbstractUserDetailsAuthenticationProvider.badCredentials"
,
"Bad credentials"
));
}
}
@Override
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
if
(
authentication
.
getCredentials
()
==
null
)
{
log
.
debug
(
"Failed to authenticate since no credentials provided"
);
throw
new
BadCredentialsException
(
"Bad credentials"
);
}
CustomAppAuthenticationToken
requestToken
=
(
CustomAppAuthenticationToken
)
authentication
;
// 此处已获得 客户端认证 获取对应 userDetailsService
Authentication
clientAuthentication
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
String
clientId
=
clientAuthentication
.
getName
();
Map
<
String
,
YifuUserDetailsService
>
userDetailsServiceMap
=
SpringUtil
.
getBeansOfType
(
YifuUserDetailsService
.
class
);
Optional
<
YifuUserDetailsService
>
optional
=
userDetailsServiceMap
.
values
().
stream
()
.
filter
(
service
->
service
.
support
(
clientId
,
requestToken
.
getGrantType
()))
.
max
(
Comparator
.
comparingInt
(
Ordered:
:
getOrder
));
if
(!
optional
.
isPresent
())
{
throw
new
InternalAuthenticationServiceException
(
"UserDetailsService error , not register"
);
}
// 手机号
String
phone
=
authentication
.
getName
();
UserDetails
userDetails
=
optional
.
get
().
loadUserByUsername
(
phone
);
// userDeails 校验
preAuthenticationChecks
.
check
(
userDetails
);
CustomAppAuthenticationToken
token
=
new
CustomAppAuthenticationToken
(
userDetails
);
token
.
setDetails
(
authentication
.
getDetails
());
return
token
;
}
/****
* 手动加载用户信息
*/
@Override
protected
UserDetails
retrieveUser
(
String
phone
,
UsernamePasswordAuthenticationToken
authentication
)
throws
AuthenticationException
{
return
null
;
}
@Override
public
boolean
supports
(
Class
<?>
authentication
)
{
return
authentication
.
isAssignableFrom
(
CustomAppAuthenticationToken
.
class
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/grant/CustomAppAuthenticationToken.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
grant
;
import
lombok.Getter
;
import
org.springframework.security.authentication.AbstractAuthenticationToken
;
import
org.springframework.security.core.authority.AuthorityUtils
;
import
org.springframework.security.core.userdetails.UserDetails
;
/**
* @author hzq
* @since 2021-09-14
*/
public
class
CustomAppAuthenticationToken
extends
AbstractAuthenticationToken
{
private
final
Object
principal
;
// 验证码/密码
private
String
code
;
/**
* 授权类型
*/
@Getter
private
String
grantType
;
public
CustomAppAuthenticationToken
(
String
phone
,
String
code
,
String
grantType
)
{
super
(
AuthorityUtils
.
NO_AUTHORITIES
);
this
.
principal
=
phone
;
this
.
code
=
code
;
this
.
grantType
=
grantType
;
}
public
CustomAppAuthenticationToken
(
UserDetails
sysUser
)
{
super
(
sysUser
.
getAuthorities
());
this
.
principal
=
sysUser
;
super
.
setAuthenticated
(
true
);
// 设置认证成功 必须
}
@Override
public
Object
getPrincipal
()
{
return
this
.
principal
;
}
@Override
public
Object
getCredentials
()
{
return
this
.
code
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/grant/ResourceOwnerCustomAppTokenGranter.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
grant
;
import
cn.hutool.core.util.StrUtil
;
import
org.springframework.security.authentication.AbstractAuthenticationToken
;
import
org.springframework.security.authentication.AccountStatusException
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.oauth2.common.exceptions.InvalidGrantException
;
import
org.springframework.security.oauth2.provider.*
;
import
org.springframework.security.oauth2.provider.token.AbstractTokenGranter
;
import
org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
/**
* 资源所有者电话令牌授予者
*
* @author hzq
* @since 2021-09-14
*/
public
class
ResourceOwnerCustomAppTokenGranter
extends
AbstractTokenGranter
{
private
static
final
String
GRANT_TYPE
=
"app"
;
private
final
AuthenticationManager
authenticationManager
;
public
ResourceOwnerCustomAppTokenGranter
(
AuthenticationManager
authenticationManager
,
AuthorizationServerTokenServices
tokenServices
,
ClientDetailsService
clientDetailsService
,
OAuth2RequestFactory
requestFactory
)
{
this
(
authenticationManager
,
tokenServices
,
clientDetailsService
,
requestFactory
,
GRANT_TYPE
);
}
protected
ResourceOwnerCustomAppTokenGranter
(
AuthenticationManager
authenticationManager
,
AuthorizationServerTokenServices
tokenServices
,
ClientDetailsService
clientDetailsService
,
OAuth2RequestFactory
requestFactory
,
String
grantType
)
{
super
(
tokenServices
,
clientDetailsService
,
requestFactory
,
grantType
);
this
.
authenticationManager
=
authenticationManager
;
}
@Override
protected
OAuth2Authentication
getOAuth2Authentication
(
ClientDetails
client
,
TokenRequest
tokenRequest
)
{
Map
<
String
,
String
>
parameters
=
new
LinkedHashMap
<>(
tokenRequest
.
getRequestParameters
());
// 手机号
String
mobile
=
parameters
.
get
(
"mobile"
);
// 验证码/密码
String
code
=
parameters
.
get
(
"code"
);
if
(
StrUtil
.
isBlank
(
mobile
)
||
StrUtil
.
isBlank
(
code
))
{
throw
new
InvalidGrantException
(
"Bad credentials [ params must be has phone with code ]"
);
}
// Protect from downstream leaks of code
parameters
.
remove
(
"code"
);
Authentication
userAuth
=
new
CustomAppAuthenticationToken
(
mobile
,
code
,
tokenRequest
.
getGrantType
());
((
AbstractAuthenticationToken
)
userAuth
).
setDetails
(
parameters
);
try
{
userAuth
=
authenticationManager
.
authenticate
(
userAuth
);
}
catch
(
AccountStatusException
|
BadCredentialsException
ase
)
{
// covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
throw
new
InvalidGrantException
(
ase
.
getMessage
());
}
// If the phone/code are wrong the spec says we should send 400/invalid grant
if
(
userAuth
==
null
||
!
userAuth
.
isAuthenticated
())
{
throw
new
InvalidGrantException
(
"Could not authenticate user: "
+
mobile
);
}
OAuth2Request
storedOAuth2Request
=
getRequestFactory
().
createOAuth2Request
(
client
,
tokenRequest
);
return
new
OAuth2Authentication
(
storedOAuth2Request
,
userAuth
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/handler/AbstractAuthenticationFailureEventHandler.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
handler
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
/**
* @author lengleng
* @date 2019/2/1 认证失败事件处理器
*/
public
abstract
class
AbstractAuthenticationFailureEventHandler
implements
ApplicationListener
<
AbstractAuthenticationFailureEvent
>
{
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public
void
onApplicationEvent
(
AbstractAuthenticationFailureEvent
event
)
{
AuthenticationException
authenticationException
=
event
.
getException
();
Authentication
authentication
=
(
Authentication
)
event
.
getSource
();
handle
(
authenticationException
,
authentication
);
}
/**
* 处理登录成功方法
* <p>
* @param authenticationException 登录的authentication 对象
* @param authentication 登录的authenticationException 对象
*/
public
abstract
void
handle
(
AuthenticationException
authenticationException
,
Authentication
authentication
);
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/handler/AbstractAuthenticationSuccessEventHandler.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
handler
;
import
cn.hutool.core.collection.CollUtil
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.security.authentication.event.AuthenticationSuccessEvent
;
import
org.springframework.security.core.Authentication
;
/**
* @author lengleng
* @date 2019/2/1 认证成功事件处理器
*/
public
abstract
class
AbstractAuthenticationSuccessEventHandler
implements
ApplicationListener
<
AuthenticationSuccessEvent
>
{
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public
void
onApplicationEvent
(
AuthenticationSuccessEvent
event
)
{
Authentication
authentication
=
(
Authentication
)
event
.
getSource
();
if
(
CollUtil
.
isNotEmpty
(
authentication
.
getAuthorities
()))
{
handle
(
authentication
);
}
}
/**
* 处理登录成功方法
* <p>
* 获取到登录的authentication 对象
* @param authentication 登录对象
*/
public
abstract
void
handle
(
Authentication
authentication
);
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/handler/AbstractLogoutSuccessEventHandler.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
handler
;
import
cn.hutool.core.collection.CollUtil
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.security.authentication.event.LogoutSuccessEvent
;
import
org.springframework.security.core.Authentication
;
/**
* @author zhangran
* @date 2021/6/23 退出成功事件处理器
*/
public
abstract
class
AbstractLogoutSuccessEventHandler
implements
ApplicationListener
<
LogoutSuccessEvent
>
{
/**
* Handle an application event.
* @param event the event to respond to
*/
@Override
public
void
onApplicationEvent
(
LogoutSuccessEvent
event
)
{
Authentication
authentication
=
(
Authentication
)
event
.
getSource
();
if
(
CollUtil
.
isNotEmpty
(
authentication
.
getAuthorities
()))
{
handle
(
authentication
);
}
}
/**
* 处理退出成功方法
* <p>
* 获取到登录的authentication 对象
* @param authentication 登录对象
*/
public
abstract
void
handle
(
Authentication
authentication
);
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/handler/FormAuthenticationFailureHandler.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
handler
;
import
cn.hutool.core.util.CharsetUtil
;
import
cn.hutool.http.HttpUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.WebUtils
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.web.authentication.AuthenticationFailureHandler
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
/**
* @author lengleng
* @date 2019-08-20
* <p>
* 表单登录失败处理逻辑
*/
@Slf4j
public
class
FormAuthenticationFailureHandler
implements
AuthenticationFailureHandler
{
/**
* Called when an authentication attempt fails.
* @param request the request during which the authentication attempt occurred.
* @param response the response.
* @param exception the exception which was thrown to reject the authentication
*/
@Override
@SneakyThrows
public
void
onAuthenticationFailure
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
exception
)
{
log
.
debug
(
"表单登录失败:{}"
,
exception
.
getLocalizedMessage
());
String
url
=
HttpUtil
.
encodeParams
(
String
.
format
(
"/token/login?error=%s"
,
exception
.
getMessage
()),
CharsetUtil
.
CHARSET_UTF_8
);
WebUtils
.
getResponse
().
sendRedirect
(
url
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/handler/SsoLogoutSuccessHandler.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
handler
;
import
cn.hutool.core.util.StrUtil
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.web.authentication.logout.LogoutSuccessHandler
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author lengleng
* @date 2020/10/6
* <p>
* sso 退出功能 ,根据客户端传入跳转
*/
public
class
SsoLogoutSuccessHandler
implements
LogoutSuccessHandler
{
private
static
final
String
REDIRECT_URL
=
"redirect_url"
;
@Override
public
void
onLogoutSuccess
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Authentication
authentication
)
throws
IOException
{
if
(
response
==
null
)
{
return
;
}
// 获取请求参数中是否包含 回调地址
String
redirectUrl
=
request
.
getParameter
(
REDIRECT_URL
);
if
(
StrUtil
.
isNotBlank
(
redirectUrl
))
{
response
.
sendRedirect
(
redirectUrl
);
}
else
{
// 默认跳转referer 地址
String
referer
=
request
.
getHeader
(
HttpHeaders
.
REFERER
);
response
.
sendRedirect
(
referer
);
}
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/service/YifuAppUserDetailsServiceImpl.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
service
;
import
com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserInfo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cache.Cache
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.security.core.userdetails.UserDetails
;
/**
* 用户详细信息
*
* @author lengleng hccake
*/
@Slf4j
@RequiredArgsConstructor
public
class
YifuAppUserDetailsServiceImpl
implements
YifuUserDetailsService
{
//private final RemoteUserService remoteUserService;
private
final
CacheManager
cacheManager
;
/**
* 手机号登录
* @param phone 手机号
* @return
*/
@Override
@SneakyThrows
public
UserDetails
loadUserByUsername
(
String
phone
)
{
Cache
cache
=
cacheManager
.
getCache
(
CacheConstants
.
USER_DETAILS
);
if
(
cache
!=
null
&&
cache
.
get
(
phone
)
!=
null
)
{
return
(
YifuUser
)
cache
.
get
(
phone
).
get
();
}
R
<
UserInfo
>
result
=
null
;
//remoteUserService.infoByMobile(phone, SecurityConstants.FROM_IN);
UserDetails
userDetails
=
getUserDetails
(
result
);
if
(
cache
!=
null
)
{
cache
.
put
(
phone
,
userDetails
);
}
return
userDetails
;
}
/**
* check-token 使用
* @param yifuUser user
* @return
*/
@Override
public
UserDetails
loadUserByUser
(
YifuUser
yifuUser
)
{
return
this
.
loadUserByUsername
(
yifuUser
.
getPhone
());
}
/**
* 是否支持此客户端校验
* @param clientId 目标客户端
* @return true/false
*/
@Override
public
boolean
support
(
String
clientId
,
String
grantType
)
{
return
SecurityConstants
.
APP
.
equals
(
grantType
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/service/YifuClientDetailsService.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
service
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants
;
import
lombok.SneakyThrows
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.security.oauth2.provider.ClientDetails
;
import
org.springframework.security.oauth2.provider.client.JdbcClientDetailsService
;
import
javax.sql.DataSource
;
/**
* @author lengleng
* @date 2019/2/1
* <p>
* see JdbcClientDetailsService
*/
public
class
YifuClientDetailsService
extends
JdbcClientDetailsService
{
public
YifuClientDetailsService
(
DataSource
dataSource
)
{
super
(
dataSource
);
}
/**
* 重写原生方法支持redis缓存
* @param clientId
* @return
*/
@Override
@SneakyThrows
@Cacheable
(
value
=
CacheConstants
.
CLIENT_DETAILS_KEY
,
key
=
"#clientId"
,
unless
=
"#result == null"
)
public
ClientDetails
loadClientByClientId
(
String
clientId
)
{
return
super
.
loadClientByClientId
(
clientId
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/service/YifuCustomTokenServices.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
service
;
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
;
/**
* 自定义 token 放发处理逻辑
*
* @author lengleng
* @date 2021/10/15
*/
public
class
YifuCustomTokenServices
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
()
{
Assert
.
notNull
(
tokenStore
,
"tokenStore must be set"
);
}
@Override
public
OAuth2AccessToken
createAccessToken
(
OAuth2Authentication
authentication
)
throws
AuthenticationException
{
OAuth2AccessToken
existingAccessToken
=
tokenStore
.
getAccessToken
(
authentication
);
OAuth2RefreshToken
refreshToken
=
null
;
// 若已产生token , 过期时删除相关token,执行下边的重新生成逻辑
if
(
existingAccessToken
!=
null
)
{
tokenStore
.
removeAccessToken
(
existingAccessToken
);
if
(
existingAccessToken
.
getRefreshToken
()
!=
null
)
{
refreshToken
=
existingAccessToken
.
getRefreshToken
();
tokenStore
.
removeRefreshToken
(
refreshToken
);
}
}
if
(
refreshToken
==
null
)
{
refreshToken
=
createRefreshToken
(
authentication
);
}
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
);
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
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/service/YifuUserDetailsService.java
deleted
100644 → 0
View file @
596dbc81
package
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
service
;
import
cn.hutool.core.util.ArrayUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserInfo
;
import
com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysUser
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
org.springframework.core.Ordered
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.AuthorityUtils
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Set
;
/**
* @author lengleng
* @date 2021/12/21
*/
public
interface
YifuUserDetailsService
extends
UserDetailsService
,
Ordered
{
/**
* 是否支持此客户端校验
* @param clientId 目标客户端
* @return true/false
*/
default
boolean
support
(
String
clientId
,
String
grantType
)
{
return
true
;
}
/**
* 排序值 默认取最大的
* @return 排序值
*/
default
int
getOrder
()
{
return
0
;
}
/**
* 构建userdetails
* @param result 用户信息
* @return UserDetails
*/
default
UserDetails
getUserDetails
(
R
<
UserInfo
>
result
)
{
if
(
result
==
null
||
result
.
getData
()
==
null
)
{
throw
new
UsernameNotFoundException
(
"用户不存在"
);
}
UserInfo
info
=
result
.
getData
();
Set
<
String
>
dbAuthsSet
=
new
HashSet
<>();
if
(
ArrayUtil
.
isNotEmpty
(
info
.
getRoles
()))
{
// 获取角色
Arrays
.
stream
(
info
.
getRoles
()).
forEach
(
role
->
dbAuthsSet
.
add
(
SecurityConstants
.
ROLE
+
role
));
// 获取资源
dbAuthsSet
.
addAll
(
Arrays
.
asList
(
info
.
getPermissions
()));
}
Collection
<?
extends
GrantedAuthority
>
authorities
=
AuthorityUtils
.
createAuthorityList
(
dbAuthsSet
.
toArray
(
new
String
[
0
]));
SysUser
user
=
info
.
getSysUser
();
// 构造security用户
return
new
YifuUser
(
user
.
getUserId
(),
user
.
getDeptId
(),
user
.
getDeptName
(),
user
.
getUsername
(),
user
.
getNickname
(),
user
.
getSystemFlag
(),
SecurityConstants
.
BCRYPT
+
user
.
getPassword
(),
user
.
getPhone
(),
true
,
true
,
true
,
StrUtil
.
equals
(
user
.
getLockFlag
(),
CommonConstants
.
STATUS_NORMAL
),
user
.
getUserGroup
(),
authorities
,
user
.
getLdapDn
());
}
/**
* 通过用户实体查询
* @param yifuUser user
* @return
*/
default
UserDetails
loadUserByUser
(
YifuUser
yifuUser
)
{
return
this
.
loadUserByUsername
(
yifuUser
.
getUsername
());
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/service/YifuUserDetailsServiceImpl.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
service
;
import
com.yifu.cloud.plus.v1.yifu.admin.api.dto.UserInfo
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.util.R
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprUpmsProperties
;
import
com.yifu.cloud.plus.v1.yifu.common.dapr.util.HttpDaprUtil
;
import
lombok.RequiredArgsConstructor
;
import
lombok.SneakyThrows
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.cache.Cache
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.security.core.userdetails.UserDetails
;
/**
* 用户详细信息
*
* @author lengleng hccake
*/
@Slf4j
@Primary
@EnableConfigurationProperties
(
DaprUpmsProperties
.
class
)
@RequiredArgsConstructor
public
class
YifuUserDetailsServiceImpl
implements
YifuUserDetailsService
{
//private final RemoteUserService remoteUserService;
private
final
CacheManager
cacheManager
;
private
final
DaprUpmsProperties
daprUpmsProperties
;
/**
* 用户名密码登录
* @param username 用户名
* @return
*/
@Override
@SneakyThrows
public
UserDetails
loadUserByUsername
(
String
username
)
{
Cache
cache
=
cacheManager
.
getCache
(
CacheConstants
.
USER_DETAILS
);
Object
o
=
cache
.
get
(
username
);
if
(
cache
!=
null
&&
cache
.
get
(
username
)
!=
null
)
{
return
(
YifuUser
)
cache
.
get
(
username
).
get
();
}
R
<
UserInfo
>
result
;
// = remoteUserService.info(username, SecurityConstants.FROM_IN);
result
=
HttpDaprUtil
.
invokeMethodGet
(
daprUpmsProperties
.
getAppUrl
(),
daprUpmsProperties
.
getAppId
(),
"/user/getInfoByUsername"
,
"?username="
+
username
,
UserInfo
.
class
);
UserDetails
userDetails
=
getUserDetails
(
result
);
if
(
cache
!=
null
)
{
cache
.
put
(
username
,
userDetails
);
}
return
userDetails
;
}
@Override
public
int
getOrder
()
{
return
Integer
.
MIN_VALUE
;
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/util/AuthUtils.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
util
;
import
cn.hutool.core.codec.Base64
;
import
cn.hutool.core.util.CharsetUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants
;
import
lombok.SneakyThrows
;
import
lombok.experimental.UtilityClass
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpHeaders
;
import
javax.servlet.http.HttpServletRequest
;
/**
* @author lengleng
* @date 2019/2/1 认证授权相关工具类
*/
@Slf4j
@UtilityClass
public
class
AuthUtils
{
private
final
String
BASIC_
=
"Basic "
;
/**
* 从header 请求中的clientId/clientsecect
* @param header header中的参数
*/
@SneakyThrows
public
String
[]
extractAndDecodeHeader
(
String
header
)
{
byte
[]
base64Token
=
header
.
substring
(
6
).
getBytes
(
CommonConstants
.
UTF8
);
byte
[]
decoded
;
try
{
decoded
=
Base64
.
decode
(
base64Token
);
}
catch
(
IllegalArgumentException
e
)
{
throw
new
RuntimeException
(
"Failed to decode basic authentication token"
);
}
String
token
=
new
String
(
decoded
,
CharsetUtil
.
UTF_8
);
int
delim
=
token
.
indexOf
(
":"
);
if
(
delim
==
-
1
)
{
throw
new
RuntimeException
(
"Invalid basic authentication token"
);
}
return
new
String
[]
{
token
.
substring
(
0
,
delim
),
token
.
substring
(
delim
+
1
)
};
}
/**
* *从header 请求中的clientId/clientsecect
* @param request
* @return
*/
@SneakyThrows
public
String
[]
extractAndDecodeHeader
(
HttpServletRequest
request
)
{
String
header
=
request
.
getHeader
(
HttpHeaders
.
AUTHORIZATION
);
if
(
header
==
null
||
!
header
.
startsWith
(
BASIC_
))
{
throw
new
RuntimeException
(
"请求头中client信息为空"
);
}
return
extractAndDecodeHeader
(
header
);
}
}
yifu-common/yifu-common-security/src/main/java/com/yifu.cloud.plus.v1/yifu/common/security/util/SecurityUtils.java
deleted
100644 → 0
View file @
596dbc81
/*
* Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
*
* 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
com
.
yifu
.
cloud
.
plus
.
v1
.
yifu
.
common
.
security
.
util
;
import
cn.hutool.core.util.StrUtil
;
import
com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants
;
import
com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser
;
import
lombok.experimental.UtilityClass
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
/**
* 安全工具类
*
* @author L.cm
*/
@UtilityClass
public
class
SecurityUtils
{
/**
* 获取Authentication
*/
public
Authentication
getAuthentication
()
{
return
SecurityContextHolder
.
getContext
().
getAuthentication
();
}
/**
* 获取用户
*/
public
YifuUser
getUser
(
Authentication
authentication
)
{
Object
principal
=
authentication
.
getPrincipal
();
if
(
principal
instanceof
YifuUser
)
{
return
(
YifuUser
)
principal
;
}
return
null
;
}
/**
* 获取用户
*/
public
YifuUser
getUser
()
{
Authentication
authentication
=
getAuthentication
();
if
(
authentication
==
null
)
{
return
null
;
}
return
getUser
(
authentication
);
}
/**
* 获取用户角色信息
* @return 角色集合
*/
public
List
<
Long
>
getRoles
()
{
Authentication
authentication
=
getAuthentication
();
Collection
<?
extends
GrantedAuthority
>
authorities
=
authentication
.
getAuthorities
();
List
<
Long
>
roleIds
=
new
ArrayList
<>();
authorities
.
stream
().
filter
(
granted
->
StrUtil
.
startWith
(
granted
.
getAuthority
(),
SecurityConstants
.
ROLE
))
.
forEach
(
granted
->
{
String
id
=
StrUtil
.
removePrefix
(
granted
.
getAuthority
(),
SecurityConstants
.
ROLE
);
roleIds
.
add
(
Long
.
parseLong
(
id
));
});
return
roleIds
;
}
}
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