Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
wwwanlingxiao
mall
Commits
f1bec5df
Commit
f1bec5df
authored
Feb 16, 2020
by
macro
Browse files
添加基于路径的动态权限支持
parent
167e2d6c
Changes
6
Hide whitespace changes
Inline
Side-by-side
mall-security/src/main/java/com/macro/mall/security/component/DynamicAccessDecisionManager.java
0 → 100644
View file @
f1bec5df
package
com.macro.mall.security.component
;
import
cn.hutool.core.collection.CollUtil
;
import
org.springframework.security.access.AccessDecisionManager
;
import
org.springframework.security.access.AccessDeniedException
;
import
org.springframework.security.access.ConfigAttribute
;
import
org.springframework.security.authentication.InsufficientAuthenticationException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
java.util.Collection
;
import
java.util.Iterator
;
/**
* 动态权限决策管理器,用于判断用户是否有访问权限
* Created by macro on 2020/2/7.
*/
public
class
DynamicAccessDecisionManager
implements
AccessDecisionManager
{
@Override
public
void
decide
(
Authentication
authentication
,
Object
object
,
Collection
<
ConfigAttribute
>
configAttributes
)
throws
AccessDeniedException
,
InsufficientAuthenticationException
{
// 当接口未被配置资源时直接放行
if
(
CollUtil
.
isEmpty
(
configAttributes
))
{
return
;
}
Iterator
<
ConfigAttribute
>
iterator
=
configAttributes
.
iterator
();
while
(
iterator
.
hasNext
())
{
ConfigAttribute
configAttribute
=
iterator
.
next
();
//将访问所需资源或用户拥有资源进行比对
String
needAuthority
=
configAttribute
.
getAttribute
();
for
(
GrantedAuthority
grantedAuthority
:
authentication
.
getAuthorities
())
{
if
(
needAuthority
.
trim
().
equals
(
grantedAuthority
.
getAuthority
()))
{
return
;
}
}
}
throw
new
AccessDeniedException
(
"抱歉,您没有访问权限"
);
}
@Override
public
boolean
supports
(
ConfigAttribute
configAttribute
)
{
return
true
;
}
@Override
public
boolean
supports
(
Class
<?>
aClass
)
{
return
true
;
}
}
mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityFilter.java
0 → 100644
View file @
f1bec5df
package
com.macro.mall.security.component
;
import
com.macro.mall.security.config.IgnoreUrlsConfig
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.security.access.SecurityMetadataSource
;
import
org.springframework.security.access.intercept.AbstractSecurityInterceptor
;
import
org.springframework.security.access.intercept.InterceptorStatusToken
;
import
org.springframework.security.web.FilterInvocation
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.PathMatcher
;
import
javax.servlet.*
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.IOException
;
/**
* 动态权限过滤器,用于实现基于路径的动态权限过滤
* Created by macro on 2020/2/7.
*/
public
class
DynamicSecurityFilter
extends
AbstractSecurityInterceptor
implements
Filter
{
@Autowired
private
DynamicSecurityMetadataSource
dynamicSecurityMetadataSource
;
@Autowired
private
IgnoreUrlsConfig
ignoreUrlsConfig
;
@Autowired
public
void
setMyAccessDecisionManager
(
DynamicAccessDecisionManager
dynamicAccessDecisionManager
)
{
super
.
setAccessDecisionManager
(
dynamicAccessDecisionManager
);
}
@Override
public
void
init
(
FilterConfig
filterConfig
)
throws
ServletException
{
}
@Override
public
void
doFilter
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
servletRequest
;
FilterInvocation
fi
=
new
FilterInvocation
(
servletRequest
,
servletResponse
,
filterChain
);
//OPTIONS请求直接放行
if
(
request
.
getMethod
().
equals
(
HttpMethod
.
OPTIONS
.
toString
())){
fi
.
getChain
().
doFilter
(
fi
.
getRequest
(),
fi
.
getResponse
());
return
;
}
//白名单请求直接放行
PathMatcher
pathMatcher
=
new
AntPathMatcher
();
for
(
String
path
:
ignoreUrlsConfig
.
getUrls
())
{
if
(
pathMatcher
.
match
(
path
,
request
.
getRequestURI
())){
fi
.
getChain
().
doFilter
(
fi
.
getRequest
(),
fi
.
getResponse
());
return
;
}
}
//此处会调用AccessDecisionManager中的decide方法进行鉴权操作
InterceptorStatusToken
token
=
super
.
beforeInvocation
(
fi
);
try
{
fi
.
getChain
().
doFilter
(
fi
.
getRequest
(),
fi
.
getResponse
());
}
finally
{
super
.
afterInvocation
(
token
,
null
);
}
}
@Override
public
void
destroy
()
{
}
@Override
public
Class
<?>
getSecureObjectClass
()
{
return
FilterInvocation
.
class
;
}
@Override
public
SecurityMetadataSource
obtainSecurityMetadataSource
()
{
return
dynamicSecurityMetadataSource
;
}
}
mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityMetadataSource.java
0 → 100644
View file @
f1bec5df
package
com.macro.mall.security.component
;
import
cn.hutool.core.util.URLUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.access.ConfigAttribute
;
import
org.springframework.security.web.FilterInvocation
;
import
org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.PathMatcher
;
import
javax.annotation.PostConstruct
;
import
java.util.*
;
/**
* 动态权限数据源,用于获取动态权限规则
* Created by macro on 2020/2/7.
*/
public
class
DynamicSecurityMetadataSource
implements
FilterInvocationSecurityMetadataSource
{
private
static
Map
<
String
,
ConfigAttribute
>
configAttributeMap
=
null
;
@Autowired
private
DynamicSecurityService
dynamicSecurityService
;
@PostConstruct
public
void
loadDataSource
()
{
configAttributeMap
=
dynamicSecurityService
.
loadDataSource
();
}
public
void
clearDataSource
()
{
configAttributeMap
.
clear
();
configAttributeMap
=
null
;
}
@Override
public
Collection
<
ConfigAttribute
>
getAttributes
(
Object
o
)
throws
IllegalArgumentException
{
if
(
configAttributeMap
==
null
)
this
.
loadDataSource
();
List
<
ConfigAttribute
>
configAttributes
=
new
ArrayList
<>();
//获取当前访问的路径
String
url
=
((
FilterInvocation
)
o
).
getRequestUrl
();
String
path
=
URLUtil
.
getPath
(
url
);
PathMatcher
pathMatcher
=
new
AntPathMatcher
();
Iterator
<
String
>
iterator
=
configAttributeMap
.
keySet
().
iterator
();
//获取访问该路径所需资源
while
(
iterator
.
hasNext
())
{
String
pattern
=
iterator
.
next
();
if
(
pathMatcher
.
match
(
pattern
,
path
))
{
configAttributes
.
add
(
configAttributeMap
.
get
(
pattern
));
}
}
// 未设置操作请求权限,返回空集合
return
configAttributes
;
}
@Override
public
Collection
<
ConfigAttribute
>
getAllConfigAttributes
()
{
return
null
;
}
@Override
public
boolean
supports
(
Class
<?>
aClass
)
{
return
true
;
}
}
mall-security/src/main/java/com/macro/mall/security/component/DynamicSecurityService.java
0 → 100644
View file @
f1bec5df
package
com.macro.mall.security.component
;
import
org.springframework.security.access.ConfigAttribute
;
import
java.util.Map
;
/**
* 动态权限相关业务类
* Created by macro on 2020/2/7.
*/
public
interface
DynamicSecurityService
{
/**
* 加载资源ANT通配符和资源对应MAP
*/
Map
<
String
,
ConfigAttribute
>
loadDataSource
();
}
mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java
View file @
f1bec5df
...
@@ -20,6 +20,8 @@ public class RestfulAccessDeniedHandler implements AccessDeniedHandler{
...
@@ -20,6 +20,8 @@ public class RestfulAccessDeniedHandler implements AccessDeniedHandler{
public
void
handle
(
HttpServletRequest
request
,
public
void
handle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
HttpServletResponse
response
,
AccessDeniedException
e
)
throws
IOException
,
ServletException
{
AccessDeniedException
e
)
throws
IOException
,
ServletException
{
response
.
setHeader
(
"Access-Control-Allow-Origin"
,
"*"
);
response
.
setHeader
(
"Cache-Control"
,
"no-cache"
);
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
setContentType
(
"application/json"
);
response
.
setContentType
(
"application/json"
);
response
.
getWriter
().
println
(
JSONUtil
.
parse
(
CommonResult
.
forbidden
(
e
.
getMessage
())));
response
.
getWriter
().
println
(
JSONUtil
.
parse
(
CommonResult
.
forbidden
(
e
.
getMessage
())));
...
...
mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java
View file @
f1bec5df
package
com.macro.mall.security.config
;
package
com.macro.mall.security.config
;
import
com.macro.mall.security.component.JwtAuthenticationTokenFilter
;
import
com.macro.mall.security.component.*
;
import
com.macro.mall.security.component.RestAuthenticationEntryPoint
;
import
com.macro.mall.security.component.RestfulAccessDeniedHandler
;
import
com.macro.mall.security.util.JwtTokenUtil
;
import
com.macro.mall.security.util.JwtTokenUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.authentication.AuthenticationManager
;
...
@@ -14,6 +14,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression
...
@@ -14,6 +14,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression
import
org.springframework.security.config.http.SessionCreationPolicy
;
import
org.springframework.security.config.http.SessionCreationPolicy
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
...
@@ -23,6 +24,9 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
...
@@ -23,6 +24,9 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
*/
*/
public
class
SecurityConfig
extends
WebSecurityConfigurerAdapter
{
public
class
SecurityConfig
extends
WebSecurityConfigurerAdapter
{
@Autowired
(
required
=
false
)
private
DynamicSecurityService
dynamicSecurityService
;
@Override
@Override
protected
void
configure
(
HttpSecurity
httpSecurity
)
throws
Exception
{
protected
void
configure
(
HttpSecurity
httpSecurity
)
throws
Exception
{
ExpressionUrlAuthorizationConfigurer
<
HttpSecurity
>.
ExpressionInterceptUrlRegistry
registry
=
httpSecurity
ExpressionUrlAuthorizationConfigurer
<
HttpSecurity
>.
ExpressionInterceptUrlRegistry
registry
=
httpSecurity
...
@@ -53,6 +57,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@@ -53,6 +57,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 自定义权限拦截器JWT过滤器
// 自定义权限拦截器JWT过滤器
.
and
()
.
and
()
.
addFilterBefore
(
jwtAuthenticationTokenFilter
(),
UsernamePasswordAuthenticationFilter
.
class
);
.
addFilterBefore
(
jwtAuthenticationTokenFilter
(),
UsernamePasswordAuthenticationFilter
.
class
);
//有动态权限配置时添加动态权限校验过滤器
if
(
dynamicSecurityService
!=
null
){
registry
.
and
().
addFilterBefore
(
dynamicSecurityFilter
(),
FilterSecurityInterceptor
.
class
);
}
}
}
@Override
@Override
...
@@ -97,4 +105,23 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@@ -97,4 +105,23 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
return
new
JwtTokenUtil
();
return
new
JwtTokenUtil
();
}
}
@ConditionalOnBean
(
name
=
"dynamicSecurityService"
)
@Bean
public
DynamicAccessDecisionManager
dynamicAccessDecisionManager
()
{
return
new
DynamicAccessDecisionManager
();
}
@ConditionalOnBean
(
name
=
"dynamicSecurityService"
)
@Bean
public
DynamicSecurityFilter
dynamicSecurityFilter
()
{
return
new
DynamicSecurityFilter
();
}
@ConditionalOnBean
(
name
=
"dynamicSecurityService"
)
@Bean
public
DynamicSecurityMetadataSource
dynamicSecurityMetadataSource
()
{
return
new
DynamicSecurityMetadataSource
();
}
}
}
Write
Preview
Supports
Markdown
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