1. 程式人生 > >Spring Security 4 (03)—— 資源資訊

Spring Security 4 (03)—— 資源資訊

序言

這一篇主要是講資源的載入和認證

1.記憶體載入

 <security:http auto-config="false" use-expressions="false" > 
       <security:intercept-url pattern="/system/**" access="ROLE_ADMIN" />
       <security:intercept-url pattern="/financeReport/**" access="ROLE_USER,ROLE_ADMIN" />    
       <security:intercept-url
pattern="/**" access="ROLE_ADMIN" />
</security:http>
  • auto-config=”true” : 自動生成登入頁面
  • use-expressions=”true” : 表示access中支援hasRole這樣的函式

2.資料庫載入

在我們的實際專案中記憶體載入的方式肯定是不行的,我們使用者資訊都是存在資料庫中的。
這時我們就要配置自定義的資源載入方式。

<security:http auto-config="false" use-expressions="false"
>
<!-- 替換 許可權驗證 過濾器 --> <security:custom-filter ref="sysSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/> </security:http> <!-- 自定義認證管理,資源,許可權 --> <bean id="sysSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
>
<property name="authenticationManager" ref="sysAuthenticationManager" /> <property name="accessDecisionManager" ref="sysAccessDecisionManager" /> <property name="securityMetadataSource" ref="sysSecurityMetadataSource" /> </bean>
  • authenticationManager 就是我上一章配置的認證管理器。
  • accessDecisionManager 這個是我們自定義的資源認證管理器
  • securityMetadataSource 這個是我們自定義的資源載入器

2.1 securityMetadataSource

要實現自定的資源載入只需要實現FilterInvocationSecurityMetadataSource介面的getAttributes()方法。
例:

/**
 * 路徑-角色 載入
 * @author Admin
 *
 */
@Service
public class SysSecurityMetadataSource implements FilterInvocationSecurityMetadataSource{

    private SysSecurityService sysSecurityServiceImp;

    @Autowired
    public SysSecurityMetadataSource(SysSecurityService sysSecurityServiceImp){
        this.sysSecurityServiceImp =sysSecurityServiceImp;
    }   

    /**
     * 根據資源URL獲取角色
     */
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

        FilterInvocation  request = (FilterInvocation) object ; 
        //資源路徑
        String url=request.getRequest().getServletPath();
        //載入資源資訊
        SysResources resource = sysSecurityServiceImp.findRolesByResourceURL(url);      
        Collection<ConfigAttribute> roles =new ArrayList<ConfigAttribute>();

        if(resource == null){   //路徑 沒加許可權 
            roles.add(new SecurityConfig(SecurityFinal.ROLE_LOGIN));
        }else if (resource.getAuthorities().size() ==0){ //路徑  無角色許可權
            roles.add(new SecurityConfig(SecurityFinal.ROLE_NO_RIGHT));
        }else{
            for (String role : resource.getAuthorities()) {
                roles.add(new SecurityConfig(SecurityFinal.ROLE_+role));
            }
        }       
        return  roles;      
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }   
}

在這個地方我加了一個特殊的處理,當根據url查到null 時說明此路徑不在資源表中,此時將預設加入一個ROLE_LOGIN角色,(使用者登入後也有一個預設的ROLE_LOGIN角色,詳情請看上一章)。當根據url查到資訊,但是角色集合大小為0時說明此路徑在資源表中,只是沒有角色擁有次路徑,這時就加入一個ROLE_NO_RIGHT角色。

2.2 accessDecisionManager

要實現自定義的許可權認證只需要實現AccessDecisionManager介面的decide()
例:

/**
 *  訪問決策 管理器 (自定義)
 * @author admin
 *
 */
@Service
public class SysAccessDecisionManager implements AccessDecisionManager{

    /**
     * 角色判斷
     * authentication -- 角色的資訊
     * object --路徑
     * configAttributes -- 路徑需要的許可權
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {

        if (configAttributes == null) {
            return;
        }       
        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        while (iterator.hasNext()) {
            ConfigAttribute configAttribute = iterator.next();
            String needPermission = configAttribute.getAttribute();
            for (GrantedAuthority ga : authentication.getAuthorities()) {
                if (needPermission.equals(ga.getAuthority())) { //路徑需要的許可權和角色擁有的許可權比較
                    return;
                }
            }
        }
        // 沒有許可權讓我們去捕捉
        throw new AccessDeniedException("您當前沒有許可權!");        
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        // TODO Auto-generated method stub
        return true;
    }
}

3. 總結

以上就是資源的載入和認證