FilterInvocationSecurityMetadataSource中的getAttributes 不执行
AccessDecisionManagerye也不执行
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(loginSuccessHandler())//code3
.and()
.logout()
.logoutSuccessUrl("/home")
.permitAll()
.invalidateHttpSession(true)
.and()
.rememberMe()
.tokenValiditySeconds(1209600);
}
@Service
public class CustomInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
private SResourceService sResourceService;
private SRoleService sRoleService;
private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
public CustomInvocationSecurityMetadataSourceService(SResourceService sres,SRoleService sR) {
this.sResourceService = sres;
this.sRoleService = sR;
loadResourceDefine();
}
private void loadResourceDefine() {
List<String> query =sRoleService.findByAll();
/*
* 应当是资源为key, 权限为value。 资源通常为url, 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
* sparta
*/
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
for (String auth : query) {
ConfigAttribute ca = new SecurityConfig(auth);
List<String> query1 = sResourceService.findByRoleName(auth);
for (String res : query1) {
String url = res;
/*
* 判断资源文件和权限的对应关系,如果已经存在相关的资源url,则要通过该url为key提取出权限集合,将权限增加到权限集合中。
* sparta
*/
if (resourceMap.containsKey(url)) {
Collection<ConfigAttribute> value = resourceMap.get(url);
value.add(ca);
resourceMap.put(url, value);
} else {
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
atts.add(ca);
resourceMap.put(url, atts);
}
}
}
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
System.out.println("sdfafgaferfgagaergsrtgsrtgsrtger");
return null;
}
// 根据URL,找到相关的权限配置。
@Override
public Collection<ConfigAttribute> getAttributes(Object object)
throws IllegalArgumentException {
System.out.println("dfergwerheyjhyrururuyjr67"+object);
// object 是一个URL,被用户请求的url。
FilterInvocation filterInvocation = (FilterInvocation) object;
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
System.out.println("urlurlurluuuuuuuu"+resURL);
RequestMatcher requestMatcher = new AntPathRequestMatcher(resURL);
if(requestMatcher.matches(filterInvocation.getHttpRequest())) {
if (resourceMap == null) {
loadResourceDefine();
}
return resourceMap.get(resURL);
}
}
if (resourceMap == null) {
loadResourceDefine();
}
return resourceMap.get("/hello");
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
/*
* @(#) MyFilterSecurityInterceptor.java 2011-3-23 上午07:53:03
*
* Copyright 2011 by Sparta
*/
package cn.paybay.ticketManager.support.authentication;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
/**
* 该过滤器的主要作用就是通过spring著名的IoC生成securityMetadataSource。
* securityMetadataSource相当于本包中自定义的MyInvocationSecurityMetadataSourceService。
* 该MyInvocationSecurityMetadataSourceService的作用提从数据库提取权限和资源,装配到HashMap中,
* 供Spring Security使用,用于权限校验。
* @author sparta 11/3/29
*
*/
public class CustomFilterSecurityInterceptor
extends AbstractSecurityInterceptor
implements Filter{
private FilterInvocationSecurityMetadataSource securityMetadataSource;
public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException{
FilterInvocation fi = new FilterInvocation( request, response, chain );
invoke(fi);
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource(){
return this.securityMetadataSource;
}
public Class<? extends Object> getSecureObjectClass(){
return FilterInvocation.class;
}
public void invoke( FilterInvocation fi ) throws IOException, ServletException{
InterceptorStatusToken token = super.beforeInvocation(fi);
try{
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}finally{
super.afterInvocation(token, null);
}
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource(){
return this.securityMetadataSource;
}
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource){
this.securityMetadataSource = securityMetadataSource;
}
public void destroy(){
}
public void init( FilterConfig filterconfig ) throws ServletException{
}
}
/*
* @(#) MyAccessDecisionManager.java 2011-3-23 下午04:41:12
*
* Copyright 2011 by Sparta
*/
package cn.paybay.ticketManager.support.authentication;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/**
*AccessdecisionManager在Spring security中是很重要的。
*
*在验证部分简略提过了,所有的Authentication实现需要保存在一个GrantedAuthority对象数组中。
*这就是赋予给主体的权限。 GrantedAuthority对象通过AuthenticationManager
*保存到 Authentication对象里,然后从AccessDecisionManager读出来,进行授权判断。
*
*Spring Security提供了一些拦截器,来控制对安全对象的访问权限,例如方法调用或web请求。
*一个是否允许执行调用的预调用决定,是由AccessDecisionManager实现的。
*这个 AccessDecisionManager 被AbstractSecurityInterceptor调用,
*它用来作最终访问控制的决定。 这个AccessDecisionManager接口包含三个方法:
*
void decide(Authentication authentication, Object secureObject,
List<ConfigAttributeDefinition> config) throws AccessDeniedException;
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
从第一个方法可以看出来,AccessDecisionManager使用方法参数传递所有信息,这好像在认证评估时进行决定。
特别是,在真实的安全方法期望调用的时候,传递安全Object启用那些参数。
比如,让我们假设安全对象是一个MethodInvocation。
很容易为任何Customer参数查询MethodInvocation,
然后在AccessDecisionManager里实现一些有序的安全逻辑,来确认主体是否允许在那个客户上操作。
如果访问被拒绝,实现将抛出一个AccessDeniedException异常。
这个 supports(ConfigAttribute) 方法在启动的时候被
AbstractSecurityInterceptor调用,来决定AccessDecisionManager
是否可以执行传递ConfigAttribute。
supports(Class)方法被安全拦截器实现调用,
包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型。
*/
public class CustomAccessDecisionManager implements AccessDecisionManager {
public void decide( Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException{
System.out.println("dededededededededededede");
if( configAttributes == null ) {
return ;
}
Iterator<ConfigAttribute> ite = configAttributes.iterator();
while( ite.hasNext()){
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig)ca).getAttribute();
//ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
for( GrantedAuthority ga: authentication.getAuthorities()){
if(needRole.trim().equals(ga.getAuthority().trim())){
return;
}
}
}
throw new AccessDeniedException("");
}
public boolean supports( ConfigAttribute attribute ){
return true;
}
public boolean supports(Class<?> clazz){
return true;
}
}