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
f3d52e14
Commit
f3d52e14
authored
Nov 24, 2022
by
fangxinjiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
security
parent
cbd8c0d1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
45 changed files
with
3587 additions
and
0 deletions
+3587
-0
EnableYifuResourceServer.java
.../common/security/annotation/EnableYifuResourceServer.java
+44
-0
Inner.java
.../cloud/plus/v1/yifu/common/security/annotation/Inner.java
+44
-0
PermissionService.java
.../v1/yifu/common/security/component/PermissionService.java
+52
-0
PermitAllUrlProperties.java
...ifu/common/security/component/PermitAllUrlProperties.java
+92
-0
ResourceAuthExceptionEntryPoint.java
...n/security/component/ResourceAuthExceptionEntryPoint.java
+65
-0
YifuAuth2ExceptionSerializer.java
...mmon/security/component/YifuAuth2ExceptionSerializer.java
+50
-0
YifuBearerTokenExtractor.java
...u/common/security/component/YifuBearerTokenExtractor.java
+51
-0
YifuDaoAuthenticationProvider.java
...mon/security/component/YifuDaoAuthenticationProvider.java
+174
-0
YifuLocalResourceServerTokenServices.java
...urity/component/YifuLocalResourceServerTokenServices.java
+83
-0
YifuRedisTokenStore.java
...1/yifu/common/security/component/YifuRedisTokenStore.java
+478
-0
YifuResourceServerAutoConfiguration.java
...curity/component/YifuResourceServerAutoConfiguration.java
+54
-0
YifuResourceServerConfigurerAdapter.java
...curity/component/YifuResourceServerConfigurerAdapter.java
+78
-0
YifuResourceServerTokenRelayAutoConfiguration.java
...ponent/YifuResourceServerTokenRelayAutoConfiguration.java
+74
-0
YifuSecurityBeanDefinitionRegistrar.java
...curity/component/YifuSecurityBeanDefinitionRegistrar.java
+51
-0
YifuSecurityInnerAspect.java
...fu/common/security/component/YifuSecurityInnerAspect.java
+68
-0
YifuSecurityMessageSourceConfiguration.java
...ity/component/YifuSecurityMessageSourceConfiguration.java
+43
-0
YifuTokenStoreAutoCleanSchedule.java
...n/security/component/YifuTokenStoreAutoCleanSchedule.java
+31
-0
YifuTokenStoreAutoConfiguration.java
...n/security/component/YifuTokenStoreAutoConfiguration.java
+21
-0
YifuWebResponseExceptionTranslator.java
...ecurity/component/YifuWebResponseExceptionTranslator.java
+111
-0
DataException.java
...plus/v1/yifu/common/security/exception/DataException.java
+18
-0
ForbiddenException.java
...v1/yifu/common/security/exception/ForbiddenException.java
+44
-0
GlobalExceptionHandler.java
...ifu/common/security/exception/GlobalExceptionHandler.java
+155
-0
InvalidException.java
...s/v1/yifu/common/security/exception/InvalidException.java
+43
-0
MethodNotAllowed.java
...s/v1/yifu/common/security/exception/MethodNotAllowed.java
+44
-0
ServerErrorException.java
.../yifu/common/security/exception/ServerErrorException.java
+44
-0
TokenInvalidException.java
...yifu/common/security/exception/TokenInvalidException.java
+47
-0
UnauthorizedException.java
...yifu/common/security/exception/UnauthorizedException.java
+44
-0
YifuAuth2Exception.java
...v1/yifu/common/security/exception/YifuAuth2Exception.java
+43
-0
YifuFeignClientConfiguration.java
...u/common/security/feign/YifuFeignClientConfiguration.java
+39
-0
YifuFeignClientInterceptor.java
...ifu/common/security/feign/YifuFeignClientInterceptor.java
+73
-0
CustomAppAuthenticationProvider.java
...ommon/security/grant/CustomAppAuthenticationProvider.java
+103
-0
CustomAppAuthenticationToken.java
...u/common/security/grant/CustomAppAuthenticationToken.java
+48
-0
ResourceOwnerCustomAppTokenGranter.java
...on/security/grant/ResourceOwnerCustomAppTokenGranter.java
+78
-0
AbstractAuthenticationFailureEventHandler.java
...ty/handler/AbstractAuthenticationFailureEventHandler.java
+51
-0
AbstractAuthenticationSuccessEventHandler.java
...ty/handler/AbstractAuthenticationSuccessEventHandler.java
+51
-0
AbstractLogoutSuccessEventHandler.java
...n/security/handler/AbstractLogoutSuccessEventHandler.java
+50
-0
FormAuthenticationFailureHandler.java
...on/security/handler/FormAuthenticationFailureHandler.java
+55
-0
SsoLogoutSuccessHandler.java
...yifu/common/security/handler/SsoLogoutSuccessHandler.java
+41
-0
YifuAppUserDetailsServiceImpl.java
...ommon/security/service/YifuAppUserDetailsServiceImpl.java
+86
-0
YifuClientDetailsService.java
...ifu/common/security/service/YifuClientDetailsService.java
+51
-0
YifuCustomTokenServices.java
...yifu/common/security/service/YifuCustomTokenServices.java
+382
-0
YifuUserDetailsService.java
.../yifu/common/security/service/YifuUserDetailsService.java
+88
-0
YifuUserDetailsServiceImpl.java
...u/common/security/service/YifuUserDetailsServiceImpl.java
+79
-0
AuthUtils.java
...fu/cloud/plus/v1/yifu/common/security/util/AuthUtils.java
+81
-0
SecurityUtils.java
...loud/plus/v1/yifu/common/security/util/SecurityUtils.java
+85
-0
No files found.
yifu-common/yifu-common-security/src/main/java/com/yifu/cloud/plus/v1/yifu/common/security/annotation/EnableYifuResourceServer.java
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
This diff is collapsed.
Click to expand it.
yifu-common/yifu-common-security/src/main/java/com/yifu/cloud/plus/v1/yifu/common/security/component/YifuResourceServerAutoConfiguration.java
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
This diff is collapsed.
Click to expand it.
yifu-common/yifu-common-security/src/main/java/com/yifu/cloud/plus/v1/yifu/common/security/service/YifuUserDetailsService.java
0 → 100644
View file @
f3d52e14
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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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
0 → 100644
View file @
f3d52e14
/*
* 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