目录
1.1 Spring Security的AOP Advice思想
1.2 AbstractSecurityInterceptor
Spring Security的权限鉴定是由AccessDecisionManager接口负责的。具体来说是由其中的decide()方法负责,其定义如下。
void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException;
如你所见,该方法接收三个参数,第一个参数是包含当前用户信息的Authentication对象;第二个参数表示当前正在请求的受保护的对象,基本上来说是MethodInvocation(使用AOP)、JoinPoint(使用Aspectj)和FilterInvocation(Web请求)三种类型;第三个参数表示与当前正在访问的受保护对象的配置属性,如一个角色列表。
1.1 Spring Security的AOP Advice思想
对于使用AOP而言,我们可以使用几种不同类型的advice:before、after、throws和around。其中around advice是非常实用的,通过它我们可以控制是否要执行方法、是否要修改方法的返回值,以及是否要抛出异常。Spring Security在对方法调用和Web请求时也是使用的around advice的思想。在方法调用时,可以使用标准的Spring AOP来达到around advice的效果,而在进行Web请求时是通过标准的Filter来达到around advice的效果。
对于大部分人而言都比较喜欢对Service层的方法调用进行权限控制,因为我们的主要业务逻辑都是在Service层进行实现的。如果你只是想保护Service层的方法,那么使用Spring AOP就可以了。如果你需要直接保护领域对象,那么你可以考虑使用Aspectj。
你可以选择使用Aspectj或Spring AOP对方法调用进行鉴权,或者选择使用Filter对Web请求进行鉴权。当然,你也可以选择使用这三种方式的任意组合进行鉴权。通常的做法是使用Filter对Web请求进行一个比较粗略的鉴权,辅以使用Spring AOP对Service层的方法进行较细粒度的鉴权。
1.2 AbstractSecurityInterceptor
AbstractSecurityInterceptor是一个实现了对受保护对象的访问进行拦截的抽象类,其中有几个比较重要的方法。beforeInvocation()方法实现了对访问受保护对象的权限校验,内部用到了AccessDecisionManager和AuthenticationManager;finallyInvocation()方法用于实现受保护对象请求完毕后的一些清理工作,主要是如果在beforeInvocation()中改变了SecurityContext,则在finallyInvocation()中需要将其恢复为原来的SecurityContext,该方法的调用应当包含在子类请求受保护资源时的finally语句块中;afterInvocation()方法实现了对返回结果的处理,在注入了AfterInvocationManager的情况下默认会调用其decide()方法。AbstractSecurityInterceptor只是提供了这几种方法,并且包含了默认实现,具体怎么调用将由子类负责。每一种受保护对象都拥有继承自AbstractSecurityInterceptor的拦截器类, MethodSecurityInterceptor将用于调用受保护的方法,而FilterSecurityInterceptor将用于受保护的Web请求。它们在处理受保护对象的请求时都具有一致的逻辑,具体的逻辑如下。
1、先将正在请求调用的受保护对象传递给beforeInvocation()方法进行权限鉴定。
2、权限鉴定失败就直接抛出异常了。
3、鉴定成功将尝试调用受保护对象,调用完成后,不管是成功调用,还是抛出异常,都将执行finallyInvocation()。
4、如果在调用受保护对象后没有抛出异常,则调用afterInvocation()。
以下是MethodSecurityInterceptor在进行方法调用的一段核心代码。
public Object invoke(MethodInvocation mi) throws Throwable {
InterceptorStatusToken token = super.beforeInvocation(mi);
Object result;
try {
result = mi.proceed();
} finally {
super.finallyInvocation(token);
}
returnsuper.afterInvocation(token, result);
}
1.2.1 ConfigAttribute
AbstractSecurityInterceptor的beforeInvocation()方法内部在进行鉴权的时候使用的是注入的AccessDecisionManager的decide()方法进行的。如前所述,decide()方法是需要接收一个受保护对象对应的ConfigAttribute集合的。一个ConfigAttribute可能只是一个简单的角色名称,具体将视AccessDecisionManager的实现者而定。AbstractSecurityInterceptor将使用一个SecurityMetadataSource对象来获取与受保护对象关联的ConfigAttribute集合,具体SecurityMetadataSource将由子类实现提供。ConfigAttribute将通过注解的形式定义在受保护的方法上,或者通过access属性定义在受保护的URL上。例如我们常见的<intercept-url pattern=”/**” access=”ROLE_USER,ROLE_ADMIN”/>就表示将ConfigAttribute ROLE_USER和ROLE_ADMIN应用在所有的URL请求上。对于默认的AccessDecisionManager的实现,上述配置意味着用户所拥有的权限中只要拥有一个GrantedAuthority与这两个ConfigAttribute中的一个进行匹配则允许进行访问。当然,严格的来说ConfigAttribute只是一个简单的配置属性而已,具体的解释将由AccessDecisionManager来决定。
1.2.2 RunAsManager
在某些情况下你可能会想替换保存在SecurityContext中的Authentication。这可以通过RunAsManager来实现的。在AbstractSecurityInterceptor的beforeInvocation()方法体中,在AccessDecisionManager鉴权成功后,将通过RunAsManager在现有Authentication基础上构建一个新的Authentication,如果新的Authentication不为空则将产生一个新的SecurityContext,并把新产生的Authentication存放在其中。这样在请求受保护资源时从SecurityContext中获取到的Authentication就是新产生的Authentication。待请求完成后会在finallyInvocation()中将原来的SecurityContext重新设置给SecurityContextHolder。AbstractSecurityInterceptor默认持有的是一个对RunAsManager进行空实现的NullRunAsManager。此外,Spring Security对RunAsManager有一个还有一个非空实现类RunAsManagerImpl,其在构造新的Authentication时是这样的逻辑:如果受保护对象对应的ConfigAttribute中拥有以“RUN_AS_”开头的配置属性,则在该属性前加上“ROLE_”,然后再把它作为一个GrantedAuthority赋给将要创建的Authentication(如ConfigAttribute中拥有一个“RUN_AS_ADMIN”的属性,则将构建一个“ROLE_RUN_AS_ADMIN”的GrantedAuthority),最后再利用原Authentication的principal、权限等信息构建一个新的Authentication进行返回;如果不存在任何以“RUN_AS_”开头的ConfigAttribute,则直接返回null。RunAsManagerImpl构建新的Authentication的核心代码如下所示。
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
GrantedAuthority extraAuthority = new SimpleGrantedAuthority(getRolePrefix() + attribute.getAttribute());
newAuthorities.add(extraAuthority);
}
}
if (newAuthorities.size() == 0) {
returnnull;
}
// Add existing authorities
newAuthorities.addAll(authentication.getAuthorities());
returnnew RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(),
newAuthorities, authentication.getClass());
}
1.2.3 AfterInvocationManager
在请求受保护的对象完成以后,可以通过afterInvocation()方法对返回值进行修改。AbstractSecurityInterceptor把对返回值进行修改的控制权交给其所持有的AfterInvocationManager了。AfterInvocationManager可以选择对返回值进行修改、不修改或抛出异常(如:后置权限鉴定不通过)。
以下是Spring Security官方文档提供的一张关于AbstractSecurityInterceptor相关关系的图。
(注:本文是基于Spring Security3.1.6所写)
(注:原创文章,转载请注明出处。原文地址:http://elim.iteye.com/blog/2211966)
相关推荐
在这个“springboot springsecurity动态权限控制”的主题中,我们将深入探讨如何在Spring Boot项目中集成Spring Security,实现动态权限控制,让菜单权限的管理更加灵活和高效。 首先,我们需要理解Spring Security...
Spring Security如何使用URL地址进行权限控制 Spring Security是一个功能强大且广泛应用的Java安全框架,它提供了许多功能,包括身份验证、授权、加密等。其中,权限控制是Spring Security的一个重要组件,它允许...
让我们深入探讨Spring Security在处理角色和权限方面的一些关键概念。 1. **角色与权限基础** 在Spring Security中,"角色"是赋予用户的标识,表示用户在系统中的职责或权限集合。例如,"管理员"、"用户"等。"权限...
struts2 + spring3 + hibernate3 + spring security3 + mysql + tomcat sys_users;sys_roles;sys_authorities;sys_resources;sys_users_roles;sys_roles_authorities;sys_authorities_resources; PS:此项目运行不...
5. **权限表达式**:使用Spring Security的`ExpressionBasedAccessDecisionManager`结合`SpEL (Spring Expression Language)`,可以在URL、方法等安全元数据上定义权限表达式。 6. **配置SecurityConfig**:在...
**Spring Security 用户权限项目概述** Spring Security 是一个强大的安全框架,专为 Java 应用程序设计,用于处理身份验证和授权。在这个项目中,它被用来实现用户权限管理,确保只有授权的用户才能访问特定的资源...
Spring Security 实践指南 Spring Security 是一个基于 Java 的安全框架,旨在提供身份验证、授权和访问控制等功能。下面是 Spring Security 的主要知识点: 一、身份验证(Authentication) 身份验证是指对用户...
这三份资料——"实战Spring Security 3.x.pdf"、"Spring Security 3.pdf" 和 "Spring Security使用手册.pdf" 将深入探讨这些概念,并提供实践指导,帮助读者掌握如何在实际项目中应用Spring Security。通过学习这些...
在本文中,我们将深入探讨如何使用Spring Boot、Spring Security和Thymeleaf这三个强大的Java技术栈组件来实现一个全面的权限管理系统,同时涵盖Remember-Me功能。Spring Boot简化了Spring应用的开发,Spring ...
在使用Spring Security时,开发者需要熟悉它的相关Maven依赖,这些依赖是Spring Security框架与应用程序集成的基础。通过配置Maven坐标,开发者可以在项目中引入Spring Security,从而开始安全功能的配置与开发。...
5. **角色与权限**:在SpringSecurity中,角色和权限是授权的基础。角色是预定义的一组权限,如“USER”、“ADMIN”。权限则更加具体,如“READ_FILE”、“WRITE_FILE”。我们可以通过UserDetails接口和...
在"spring security权限管理"这个主题中,我们将深入探讨如何利用Spring Security来实现复杂而灵活的权限控制。 首先,`MyUser.java`可能是自定义的用户实体类,它通常会包含用户的基本信息,如用户名、密码、角色...
本项目“SpringSecurity+OAuth2+JWT分布式权限控制”旨在提供一个完整的解决方案,帮助开发者构建安全的、基于微服务的分布式应用程序。 Spring Security 是一个强大的和高度可定制的身份验证和授权框架,适用于...
登录功能是Spring Security的基础,它提供了默认的登录页面和处理机制。你可以通过配置HttpSecurity来定制登录过程,例如设置登录URL、失败URL和成功处理器。Spring Security支持基于表单的身份验证,也支持OAuth2和...
在"SpringSecurity权限管理开发手册.pdf"和"SpringSecurity权限管理开发手册.pdf.txt"中,你将找到更多关于如何配置和使用SpringSecurity进行权限管理的详细信息,包括配置XML或Java配置、定义访问规则、处理未授权...
Spring Security 支持角色基础的授权、表达式基础的访问控制(ACE)以及权限对象的访问控制。 3. **Filter Security Interceptor (FSI) 和 Access Decision Manager (ADM)**:FSI是Spring Security的核心组件,负责...
首先,SpringSecurity的核心功能包括用户认证、权限授权、会话管理以及防止常见攻击。其中,用户认证涉及验证用户凭据,如用户名和密码,以确定用户的身份。而权限授权则决定了已认证的用户可以访问哪些资源或执行...
后端使用SpringBoot框架进行业务逻辑开发,利用Spring Security实现权限控制。数据库采用MySQL进行数据存储,使用MyBatis进行数据访问。 权限控制模块设计包括用户、角色和权限三个主要模块。用户模块用于管理用户...
本项目以SpringBoot为基础,结合SpringSecurity进行权限控制,并利用JWT(JSON Web Tokens)实现用户身份验证,为初学者提供了一个实践学习的平台。下面我们将深入探讨这些技术的使用和整合。 **1. SpringBoot** ...
在压缩包文件`spring_gateway_security_webflux`中,可能包含了示例代码或配置文件,用于演示如何在Spring Cloud Gateway中集成Spring Security,实现统一登录认证鉴权。这些资源可以帮助开发者更快地理解和实践上述...