- 前言
- 第一部分 基础应用开发
- 第 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!"); } …… }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论