Spring Security安全框架入門篇


一、Spring Security相關概念

1.1.、Spring Security介紹:

Spring Security是一個能夠為基於Spring的企業應用系統提供聲明式的安全訪問控制解決方式的安全框架(簡單說是對訪問權限進行控制嘛)。它提供了一組能夠在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能。為應用系統提供聲明式的安全訪問控制功能,降低了為企業系統安全控制編寫大量反復代碼的工作。

1.2、Spring Security實現原理:

Spring Security對Web安全性的支持大量地依賴於Servlet過濾器。通過這些過濾器攔截進入請求,推斷是否已經登錄認證且具訪問相應請求的權限。

要完畢訪問控制。Spring Security至少須要以下四個攔截器(調度器、認證管理器、權限資源關聯器、訪問決策器)進行配合完畢:

<!-- mySecurityInterceptor這里我們把它命名為調度器吧 -->
<!-- 必須包括 authenticationManager,securityMetadataSource,accessDecisionManager 三個屬性 -->   
<!-- 我們的全部控制將在這三個類中實現 --> 
<!-- 它繼承AbstractSecurityInterceptor類並實現了Filter接口 --> 
<bean id="mySecurityInterceptor" class="com.luo.Filter.MySecurityInterceptor">  
    <b:property name="authenticationManager" ref="authenticationManager" />  
    <b:property name="securityMetadataSource" ref="securityMetadataSource" />  
    <b:property name="accessDecisionManager" ref="accessDecisionManager" />  

</bean>  

<!-- 認證管理器,實現用戶認證的入口 -->  
<authentication-manager alias="authenticationManager">  
    <authentication-provider user-service-ref="myUserDetailService" />   
</authentication-manager>  

<!-- 在這個類中,你就能夠從數據庫中讀入用戶的password。角色信息等 -->  
<!-- 主要實現UserDetailsService接口就可以,然后返回用戶數據 -->  
<bean id="myUserDetailService" class="com.luo.Filter.MyUserDetailService" />  

<!-- 權限資源關聯器。將全部的資源和權限相應關系建立起來,即定義某一資源能夠被哪些角色訪問 -->  
<!-- 它實現了FilterInvocationSecurityMetadataSource接口 -->  
<bean id="securityMetadataSource" class="com.luo.Filter.MyFilterInvocationSecurityMetadataSource" /> 

<!--訪問決策器。決定某個用戶具有的角色,是否有足夠的權限去訪問某個資源 --> 
<!-- 它實現了AccessDecisionManager接口 --> 
<bean id="accessDecisionManager" class="com.luo.Filter.MyAccessDecisionManager">

看完上面的配置。可能未必能夠全然明確。以下我們再進一步說明。

(1)首先我們自己定義一個過濾器(調度器。這里我們命名為mySecurityInterceptor),這個過濾器繼承AbstractSecurityInterceptor類(這里先說明,本文但凡不是自己定義的類或接口都是Spring Security提供的,無須深究)。 它至少包括 authenticationManager,accessDecisionManager,securityMetadataSource三個屬性,我們的全部控制將在這三個類中實現。

(2)登錄驗證:自己定義類MyUserDetailService實現UserDetailsService接口和其loadUserByUsername方法,這種方法依據用戶輸入的username,從數據庫里面獲取該用戶的全部權限細信息(統稱用戶信息)。Spring Security的AuthenticationProcessingFilter攔截器調用authenticationManager,類MyUserDetailService拿到用戶信息后,authenticationManager對照用戶的password(即驗證用戶),假設通過了,那么相當於通過了AuthenticationProcessingFilter攔截器,也就是登錄驗證通過。

(3)資源訪問控制:MySecurityInterceptor繼承AbstractSecurityInterceptor、實現Filter是必須的。登陸后,每次訪問資源都會被MySecurityInterceptor這個攔截器攔截,它首先會調用MyFilterInvocationSecurityMetadataSource類的getAttributes方法獲取被攔截url所需的權限,在調用MyAccessDecisionManager類decide方法推斷用戶是否夠權限。

可能文字描寫敘述還是比較抽象。通過實例應該能讓大家更加清楚其原理。


補充說明一下:

UserDetailsService在身份認證中的作用:

Spring Security中進行身份驗證的是AuthenticationManager接口,ProviderManager是它的一個默認實現,但它並不用來處理身份認證,而是托付給配置好的AuthenticationProvider。每一個AuthenticationProvider會輪流檢查身份認證。

檢查后或者返回Authentication對象或者拋出異常。

驗證身份就是載入響應的UserDetails,看看是否和用戶輸入的賬號、password、權限等信息匹配。

此步驟由實現AuthenticationProvider的DaoAuthenticationProvider(它利用UserDetailsService驗證username、password和授權)處理。

因此,登錄認證事實上能夠不實現UserDetailsService,而是實現AuthenticationProvider,然后在AuthenticationProvider里面獲取用戶輸入的username和password進行校驗也是能夠的。或者兩者一起使用。

以下推薦兩者一起使用的方式http://blog.sina.com.cn/s/blog_4adc4b090102uy2f.html

另外,僅僅實現AuthenticationProvider而不實現UserDetailsService的方式,這類是重寫AuthenticationProvider的authenticate方法的代碼:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String inputLoginId = authentication.getName();   //獲取用戶輸入的username
    String inputPasswd = authentication.getCredentials().toString(); /獲取用戶輸入的password

    LOGGER.info("用戶{}登錄", inputLoginId);
    try{
        // 查詢此用戶信息
        myUser myUser = null;  //依據username到數據庫里面查詢用戶數據
        if (myUser == null ) {
            throw new Exception("您輸入的賬號不存在");
        }
        if (myUser.getUserStatus() == UserStatus.locked) {
            throw new Exception("您的賬號已被鎖定");
        }

        String encodedPassword = myUser.getLoginPasswd();
        // 校驗password是否正確
        boolean authenticated = verifyPassword(inputPasswd, encodedPassword);
        if (authenticated) {
            // 認證成功處理
            updateLoginInfo(myUser.getLoginId(), 0, null);
        } else {
            // 認證失敗處理
            authenticateErrorProcess(portalUser);
        }

        List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
        for (MyRole myRole : myUser.allRoleList()) {
            grantedAuths.add(new SimpleGrantedAuthority(myRole.getRoleCode()));
        }
        MyAuthUser authUser = new PortalAuthUser(inputLoginId, inputPasswd, true, true, true, true, grantedAuths);
        authUser.setPortalUser(portalUser);
        return new UsernamePasswordAuthenticationToken(authUser, null, authUser.getAuthorities());
    }catch(Exception e){
        LOGGER.warn("用戶登錄失敗", e);
        throw new Exception(" 請確認username或者password是否正確); } }

二、Spring Security實例具體說明

本實例環境:eclipse + maven
本實例採用的主要技術:spring + springmvc + spring security

時間有限這里僅僅對其訪問控制原理進行了闡述,樣例后面再補上,只是關於實例推薦參考博文:http://blog.csdn.net/u012367513/article/details/38866465,這篇文章寫得很具體!

這是春節前最后一篇博客了。過春節回來還有另外的學習計划。可能這個樣例的TODO有點遙遙無期啊……..哈哈


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM