- 前言
- 第一部分 基础应用开发
- 第 1 章 Spring Boot 入门
- 第 2 章 在 Spring Boot 中使用数据库
- 第 3 章 Spring Boot 界面设计
- 第 4 章 提高数据库访问性能
- 第 5 章 Spring Boot 安全设计
- 第二部分 分布式应用开发
- 第 6 章 Spring Boot SSO
- 第 7 章 使用分布式文件系统
- 第 8 章 云应用开发
- 第 9 章 构建高性能的服务平台
- 第三部分 核心技术源代码分析
- 第 10 章 Spring Boot 自动配置实现原理
- 第 11 章 Spring Boot 数据访问实现原理
- 第 12 章 微服务核心技术实现原理
- 附录 A 安装 Neo4j
- 附录 B 安装 MongoDB
- 附录 C 安装 Redis
- 附录 D 安装 RabbitMQ
- 结束语
5.4 权限管理设计
用户通过身份认证,成功登录系统后,就要开始检查用户访问资源的权限,如果用户没有权限访问,将会阻止用户访问受保护的资源,并给出错误提示信息。
5.4.1 权限管理配置
在安全配置类中,定义了几个类,实现自定义的权限检查判断及其管理的功能,如代码清单 5-19 所示,各个类的意义如下:
- CustomFilterSecurityInterceptor:权限管理过滤器。
- CustomAccessDecisionManager:权限管理决断器。
- CustomSecurityMetadataSource:权限配置资源管理器。
其中,过滤器在系统启动时开始工作,并同时导入资源管理器和权限决断器,对用户访问的资源进行管理。权限决断器对用户访问的资源与用户拥有的角色权限进行对比,以此来判断一个用户是否对一个资源具有访问权限。
代码清单 5-19 安全配置类中的权限管理设置
@Bean
public CustomFilterSecurityInterceptor customFilter() throws Exception{
CustomFilterSecurityInterceptor customFilter = new CustomFilterSecurityInterceptor();
customFilter.setSecurityMetadataSource(securityMetadataSource());
customFilter.setAccessDecisionManager(accessDecisionManager());
customFilter.setAuthenticationManager(authenticationManager);
return customFilter;
}
@Bean
public CustomAccessDecisionManager accessDecisionManager() {
return new CustomAccessDecisionManager();
}
@Bean
public CustomSecurityMetadataSource securityMetadataSource() {
return new CustomSecurityMetadataSource(settings.getUrlroles());
}
5.4.2 权限管理过滤器
权限管理过滤器继承于 Spring Security 的 AbstractSecurityInterceptor,实时监控用户的行为,防止用户访问未被授权的资源,如代码清单 5-20 所示。
代码清单 5-20 权限管理过滤器
public class CustomFilterSecurityInterceptor extends AbstractSecurity
Interceptor implements Filter {
private static final Logger logger = Logger.getLogger(CustomFilterSecurityInterceptor.class);
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain
chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
logger.debug("===="+fi.getRequestUrl());
invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} catch (Exception e) {
logger.error(e.getMessage());
} finally {
super.afterInvocation(token, null);
}
}
}……
5.4.3 权限配置资源管理器
权限配置资源管理器实现了 Spring Security 的 FilterInvocationSecurityMetadataSource,它在启动时导入代码清单 5-4 的权限配置列表。如代码清单 5-21 所示,权限配置资源管理器为权限决断器实时提供支持,判断用户访问的资源是否在受保护的范围之内。
代码清单 5-21 权限配置资源管理器
public class CustomSecurityMetadataSource implements FilterInvocationSecurityMetadataSource{
private static final Logger logger = Logger.getLogger(CustomSecurityMetadataSource .class);
private Map<String, Collection<ConfigAttribute>> resourceMap = null;
private PathMatcher pathMatcher = new AntPathMatcher();
private String urlroles;
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
public CustomSecurityMetadataSource (String urlroles) {
super();
this.urlroles = urlroles;
resourceMap = loadResourceMatchAuthority();
}
private Map<String, Collection<ConfigAttribute>> loadResourceMatchAuthority() {
Map<String, Collection<ConfigAttribute>> map = new HashMap<String, Collection<ConfigAttribute>>();
if(urlroles != null && !urlroles.isEmpty()){
String[] resouces = urlroles.split(";");
for(String resource : resouces){
String[] urls = resource.split("=");
String[] roles = urls[1].split(",");
Collection<ConfigAttribute> list = new ArrayList<ConfigAttri
bute>();
for(String role : roles){
ConfigAttribute config = new SecurityConfig(role.trim());
list.add(config);
}
// key:
url, value:
roles
map.put(urls[0].trim(), list);
}
}else{
logger.error("'securityconfig.urlroles' must be set");
}
logger.info("Loaded UrlRoles Resources.");
return map;
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
String url = ((FilterInvocation) object).getRequestUrl();
logger.debug("request url is " + url);
if(resourceMap == null)
resourceMap = loadResourceMatchAuthority();
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
if (pathMatcher.match(resURL,url)) {
return resourceMap.get(resURL);
}
}
return resourceMap.get(url);
}
......
}
5.4.4 权限管理决断器
权限管理的关键部分就是决断器,它实现了 Spring Security 的 AccessDecision-Manager,重载了 decide 函数,使用了自定义的决断管理,如代码清单 5-22 所示。在用户访问受保护的资源时,决断器判断用户拥有的角色中是否对该资源具有访问权限,如果没有权限将被拒绝访问,并返回错误提示。
代码清单 5-22 权限管理决断器
public class CustomAccessDecisionManager implements AccessDecisionManager {
private static final Logger logger = Logger.getLogger(CustomAccessDecisionManager.class);
@Override
public void decide(Authentication authentication, Object object, Collec
tion<ConfigAttribute> configAttributes)throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) {
return;
}
// config urlroles
Iterator<ConfigAttribute> iterator = configAttributes.iterator();
while (iterator.hasNext()) {
ConfigAttribute configAttribute = iterator.next();
// need role
String needRole = configAttribute.getAttribute();
// user roles
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needRole.equals(ga.getAuthority())) {
return;
}
}
logger.info("need role is " + needRole);
}
throw new AccessDeniedException("Cannot Access!");
}
……
}
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论