SpringMVC ——Spring Security 入門詳解

 

1.Spring Security介紹

Spring Security是基於spring的應用程序提供聲明式安全保護的安全性框架,它提供了完整的安全性解決方案,能夠在web請求級別和方法調用級別處理身份證驗證和授權.它充分使用了依賴注入和麪向切面的技術.

  Spring security主要是從兩個方面解決安全性問題:

  1. web請求級別:使用servlet過濾器保護web請求並限制URL級別的訪問
  2. 方法調用級別:使用Spring AOP保護方法調用,確保具有適當權限的用戶採用訪問安全保護的方法.

2.Web請求級別的保護

  對於請求級別的安全性來說,主要是通過保護一個或多個URL,使得只有特定的用戶才能訪問,並其他用戶訪問該URL的內容.本文主要是基於spring mvc下整合Spring security模塊.

2.1 聲明代理Servlet過濾器

  在web中的URL一般需要過濾器進行保護,所以需要藉助一系列的Servlet過濾器提供各種各樣的安全性功能.這也需要在web.xml中配置一系列相關的<filter>,使得配置文件臃腫難以閱讀.所以Spring security提供了代理Servelt過濾器可以解決該問題.如下面清單所示:

<filter>
     <filter-name>springSecurityFilterChain</filter-name>
     <filter-class>
         org.springframework.web.filter.DelegatingFilterProxy
     </filter-class>
 </filter>

   DelegatingFilterProxy是一個代理的Servelt過濾器,它主要負責將工作委託給一個javax.servlet.Filter實現類,這個實現類作爲一個<bean>已經註冊在Spring應用的上下文,且該bean的Id便是上面<filter-name>的名字,即springSecurityFilterChain.  

   springSecurityFilterChain,也可稱爲FilterChainProxy.它可以鏈接任意多個其他的過濾器,根據這些過濾器提供不同的安全特性.但是你並不需要在spring配置文件中配置該過濾器的bean和它所鏈接的其他過濾器

2.2 配置最小化web安全性和攔截請求

 <http auto-config="true">
      <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
  </http>

   在spring的配置文件中加入這段代碼可以攔截站點/admin分支行下的所有URL請求.並限制只有具備"ROLE_ADMIN"權限的用戶纔可以訪問,"ROLE_ADMIN"是自定義的一個權限.pattern默認使用的是Ant格式。如果需要使用正則表達式則在http 元素的path-type設置爲regex。<intercept-url>能夠攔截請求,主要是對指定的URL進行保護,如果用戶具有訪問指定的URL的權限則通過否則拒絕。

  <http>元素將自動創建一個FilterChainProxy以及鏈中所有的過濾器bean.同時會將FilterChainProxy的bean託管給配置在web.xml的DelegatingFilterProxy.設置auto-config="true"會自動生成一個登陸界面,可以通過http://localhost:8080/你的項目名稱/spring_security_login.設置爲ture也等價於下面的配置:

 
<http>
    <form-login />
  <!--HTTP 基本認證 -->
    <http-basic/>
  <!-- 可以通過logout-url屬性設置用戶退出的url-->
    <logout />
    <intercept pattern="/**" access="ROLE_DEMO" />
</http>

  Spring security 3.0以後加入了對SpEL的支持,可以將<http>元素的use-expressions設置爲"true"便可使用SpEL。

<http auto-config="true" use-expressions="true">
   ..
    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')">
</http>

  Spring Security 支持的所有SpEL表達式如下:

安全表達式  計算結果
authentication   用戶認證對象
denyAll   結果始終爲false
hasAnyRole(list of roles)   如果用戶被授權指定的任意權限,結果爲true
hasRole(role) 如果用戶被授予了指定的權限,結果 爲true
hasIpAddress(IP Adress) 用戶地址
isAnonymous()   是否爲匿名用戶
isAuthenticated()   不是匿名用戶
isFullyAuthenticated   不是匿名也不是remember-me認證
isRemberMe()   remember-me認證
permitAll 始終true
principal 用戶主要信息對象

2.3 通過表單安全登陸

   雖然<http>元素設置auto-config="true",可以自動生成一個自動登陸頁面。當一般開始都是採用自定義的登陸界面。所以需要進行下面配置:

<http auto-config="true">
    <!-- 設置登錄頁配置 login-page指定了登錄界面的視圖,authentication-failure-url則設置失敗後的重定向到相同的登陸界面-->
    <from-login login-processing-url="/static/j_spring_security_check"
    login-page="/login" 
    authentication-failure-url="/login?login_error=t">
</http>

  在自定義的登錄界面中將表單提交地址設置爲"/static/j_spring_security_check",同時需要將用戶名輸入框和密碼輸入框name分別設置爲j_username和j_password 。有些應用中往往會設置記住密碼,方便用戶訪問應用,不需要每次都登錄。實現該功能只需要在<http>元素中加入:

<!--key設置cookie的祕鑰的值,默認是SpringSecured。後一個屬性指定有效期  -->
<remember-me key="spitterKey" token-validity-seconds="2419200"/> 

  靜態頁面中加入:

<input  name="_spring_security_rember_me" type="checkbox"/>

2.4 強制請求使用https

  https傳輸數據比較安全,如將用戶,密碼提交可以使用https保證數據傳輸的安全。可以進行以下設置,保證每次對指定URL請求,Spring Security都會自動重定向爲https請求。不管用戶訪問時是否加入https.

<intercept pattern="/admin/**" access="ROLE_DEMO" requires-channel="https" />

3. 保護視圖

  Spring Security提供jsp標籤庫,支持視圖級別的保護,這個標籤庫包含3個標籤:

  1. <security:accesscontrollist> :如果認證用戶具有權限列表中的某一個權限,那麼這個標籤範圍的內容將顯示。
  2. <security:authentication>: 訪問當前用戶認證對象的屬性。一般用戶顯示當前用戶的用戶名之類的。具有的用戶認證信息有:
  • authorities:一組用於用戶所授予的GrantedAuthority對象
  • credentials:覈實用戶的憑據
  • detail:認證的附加信息(IP地址,會話ID等)
  • principal:用戶的主要信息對象 

  3.<security:authorize>: 如果當前用戶滿足特定全新,則顯示標籤範圍的內容。例:

<!-- 顯示用戶信息, 並將信息複製給var變量,該變量的使用範圍爲scope的範圍。var和scope可以不設置-->
 Hello <security:authentication property="principal.usrname" var="loginId" scope="request">
 <security:authorize access="hasRole('ROLE_ADMIN')">
    如果當前用戶有ROLE_ADMIN權限,則顯示這部分內容
</security:authorize>

<security:authorize>除了使用access來指定權限外還可以根據url設置具體權限,即在攔截請求中指定的url的權限。

<security:authorize url="/admin/**">
    如果當前用戶有/admin/**對應的權限,則顯示這部分內容
</security:authorize>
4.認證用戶
 前面提到很多用戶對象和用戶權限的問題,他們的關係和定義就是通過認證用戶來定義的。 Spring Security提供了以下認證策略:
  • 內存用戶存儲庫,即顯示的配置在spring配置文件中。
  • 基於jdbc的用戶存儲庫
  • 基於LDAP的用戶存儲庫
  • OpenID 分散式用戶身份識別系統
  • 中心認證服務(CAS)
  • X.509證書
  • 基於JAAS的提供者

  這裏主要是介紹基於spirng配置和jdbc的。

4.1 配置內存用戶存儲庫

首先建立一個用戶服務,配置所有用戶和權限信息。然後交給認證管理器管理,認證管理器會將認證的任務交給一個或多個認證提供者。

 

<!-- 用戶服務-->
<user-service id="userService">
    <user name="alibaba" password="123456" authorities="ROLE_ADMIN">
    <user name="baidu" password="66666" authorities="ROLE_BAIDU">
    ......
</user-service>
<!-- 認證管理器-->
<authentication-manager>
    <authentication-provider user-service-ref="userService"/>
</authentication-manager>

 

  另一種方式將認證提供者和用戶服務裝配在一起,適用於只有一種用戶服務:  

<!-- 認證提供者-->
<authentication-provider>
    <!-- 用戶服務-->
<user-service id="userService">
    <user name="alibaba" password="123456" authorities="ROLE_ADMIN">
    <user name="baidu" password="66666" authorities="ROLE_BAIDU">
    ......
</user-service>
</authentication-provider>

 

4.2 基於數據庫進行認證

    這個是最常用的是用戶認證,因爲很多應用都是採用數據庫存儲用戶數據。Spring Security提供了<jdbc-usr-service>.如果只指定了  data-source-ref得數據源,那麼spring security會自己爲我們寫sql語句從數據庫中查找用戶和權限信息。但一般情況下,提供的查詢語句並不能和我們的數據庫對應上,所以我們需要自己寫sql語句。主要包括以下屬性:

  • users-by-username-query:根據用戶名查詢用戶名,密碼以及是否可用狀態
  • authorities-by-username-query:根據用戶名查詢用戶被用戶名和授權的權限。
  • group-authorities-by-username-query:根據用戶名查詢用戶組的權限。  
<jdbc-user-service id="userService"  data-source-ref="dataSource"
      users-by-username="select username,password, true from user where username=?"
      authories-by-username-query="select username,role from user_role where username=?" />  
<authentication-manager>
    <authentication-provider user-service-ref="userService"/>
</authentication-manager>

5.保護方法調用

  spring security的方法級別的保護是基於Spring AOP技術。首先需要在spring配置文件中加以下配置,才能使spring Security保護那些使用相關注解的方法。

<global-method-security secured-annotations="enabled" />

   spring Security支持4種方法級別安全性的方法:

  1. 使用@Secured註解方法,這是spring自帶的註解方法。@Secured("")內部的字符串不具有SpEL特性,只能是具體的權限。
  2. 使用@JSR-250 @RelosAllowed註解的方法。作用和使用方法與@Secured一樣,不同在於它不是spring框架的,所以可以做到和spring框架的解耦。
  3. 使用Spring 方法調用前和調用後註解方法。這些方法支持SpEL.
  4. 匹配一個或多個明確聲明的切點方法。

5.1 @Secured和 @RelosAllowed

 

@Secured("ROLE_ADMIN")
public void addUser(User user){
    ...  
}
@RolesAllowed("ROLE_ADMIN")
public void updateUser(User user){
    ...  
}

 

5.2 使用Spring 方法調用前和調用後註解方法

 可以使用SpEL方法有四種:

  1. @PreAuthorize: 在方法調用前,基於表達式計算結果來限制方法訪問
  2. @PostAuthorize: 允許方法調用,但是如果表達式結果爲fasle則拋出異常
  3. @PostFilter :允許方法調用,但必須按表達式過濾方法結果。
  4. @PreFilter:允許方法調用,但必須在進入方法前過濾輸入值

 舉例清單

5.3 匹配一個或多個明確聲明的切點方法

    爲多個方法設置相同的授權檢查,spring security提供了 <protect-pointcut>元素。配置如下:

<global-method-security secured-annotations="enabled" >
    <protect-pointcut access="ROLE_ADMIN" expression="execution(@com.securitytest.service.UserService**.*(String)"
</global-method-security>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章