前言
上一篇学习了security的登录验证流程,现在来看一下权限校验的流程
正文
-
Interceptor与Filter的区别
Filter 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤
Interceptor 依赖于web框架,基于Java的反射机制,属于AOP的一种运用。 -
HTTP请求的权限配置和验证
从第二部分我们知道最后一个Filter是FilterSecurityInterceptor,这个类即继承了AbstractSecurityInterceptor也实现了Filter,负责处理HTTP资源的安全性,官网中给出的配置xml如下:
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
</security:filter-security-metadata-source>
</property>
</bean>
由第一部分我们知道在WebSecurityConfig中可以配置资源访问权限
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login").loginProcessingUrl("/auth/login").defaultSuccessUrl("/index")
.and()
.logout().logoutSuccessUrl("/login")
.and()
.authorizeRequests()
.antMatchers("/css/**", "/js/**","/images/**", "/static/**").permitAll()//允许访问静态资源
.antMatchers("/login","/auth/login").permitAll() // premitAll()不做拦截
.antMatchers("/index").authenticated() //authenticated() 必须登录后可见
.antMatchers("/hello").access("hasRole('ROLE_TEST')")//含有Test权限的才可以访问
.anyRequest().authenticated();
}
这个/hello 只有含有TEST权限的用户才可以访问了
http资源访问流程.png
其中AccessDecisionManager根据AccessDecisionVoter的不同结果来给出最终的权限验证结果,decide方法如下
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
int deny = 0;
for (AccessDecisionVoter voter : getDecisionVoters()) {
int result = voter.vote(authentication, object, configAttributes);
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage(
"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
-
方法级别的权限配置和验证
由第一部分我们知道可以把权限控制在方法层面上,比如
@Secured
@RolesAllowed
@PreAuthorize 方法调用之前,基于表达式的计算结果来限制对方法的访问
@PostAuthorize 方法调用之后,如果表达式的结果为false,则抛出异常
@PreFilter 方法调用之前,过滤进入方法的输入值
@PostFilter 方法调用之后,过滤方法的结果值
这些权限控制的流程跟上面的差不多,可能在AccessDecisionVoter投票器有所区别,关系图如下
投票类关系图.png
当然用户也可以根据实际需要实现自己的voter
还有就是入口,方法级别的权限控制是从MethodSecurityInterceptor类中invoke进去的
总结
基本上Security就简单的学习完了,具体的东西还是要投入到实际项目中运用才会有效果
网友评论