這篇算是一個入門文章,昨天看見有網友提問,spring mvc集成spring security 的時候出錯,揣測了一下問題木有解決。我就幫忙給搭建了一個集成框架他說可以,他告訴我這樣的文章網上少。今天我就分享在這里供入門學習。spring mvc我木有用過,所以我們這里重點講解如何集成spring security ,spring security是一個非常好的開源權限框架(具體了解自己google,或者到spring 官網,這里我給一個DOC3.1:http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity.html)。 可以說不僅僅包含了權限,里面有一套完整的授權認證系統包括:權限、防止session攻擊、支持信道安全、支持LDAP認證、支持OpenID、同時支 持CAS集成單點登錄等等,個人用過spring security 2.0基本大致一樣,當時中文資源那個少啊,尤其集成SSH+spring security 更是少的可憐,最后還是硬着頭皮上,最后拿下了這個框架,最起碼了解了。當時就寫了一個SSH+spring security的文章,還被某網站引用。好了廢話不扯,我們今天在來集成一個springmvc3.1+spring security3.1.我們step by step go。
step1:搭建SpringMVC。
如果你會搭建或者搭建好了spring MVC那這一步可以略過了。首先下載spring mvc3.1 jar這個到官網下載或者google,需要的jar如圖:
然后創建一個包新建一個spring mvc 的class、我的如下:
@Controller public class RestConstroller { public RestConstroller() {} @RequestMapping(value = "/welcome", method = RequestMethod.GET) public String registPost() { return "/hello"; } }
上面采用spring 注解方式實例化class,這個我不多講,spring mvc也沒用過不敢亂點。官網有例子你自己照着做。http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/validation.html#format-configuring-FormattingConversionService
接着新建了一個view試圖放了一個hello.jsp
然后新建一個spring-servlet.xml 這個是spring mvc的一個配置文件。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 啟動注解驅動的Spring MVC功能,注冊請求url和注解POJO類方法的映射--> <mvc:annotation-driven /> <!-- 啟動包掃描功能,以便注冊帶有@Controller、@Service、@repository、@Component等注解的類成為spring的bean --> <context:component-scan base-package="com.mvc.test" /> <!--這個包根據自己的項目來配置,我的是com.mvc.test--> <!-- 對模型視圖名稱的解析,在請求時模型視圖名稱添加前后綴 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp" /> </beans> 然后配置web.xml: <context-param> <param-name>contextConfigLocation</param-name> <!-- 應用上下文配置文件 --> <param-value>/WEB-INF/spring-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置spring核心servlet --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- url-pattern配置為/ 攔截 --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
項目具體結構:
好了現在可以啟動了,我這里啟動的時候很不幸報錯了,一看,缺少logger的jar,添加commons-logging-1.1.jar,ok啟動訪問http://localhost:8080/SpringMVC/welcome成功、
到這里spring mvc配置完成。下面我們的重點集成spring security 3.1
step 2 spring mvc3.1集成spring security 3.1
首先要講一點大版本集成要注意一點,大版本號要保持一直,第一位的往往都是大版本號,小版本號影響不大。為什么要這樣講,當時我在集成SSH 的時候spring 用的是spring 2.X,然后去下載了一個spring security 3.X的死活不成功。后來在一片老外的文章中發現了,具體地址我忘記了,spring 2.X +spring security 2.X才能集成功,spring 3.X +spring security 3.X才能集成成功。現在想想真夠二的、哈哈,好了小插曲過后,我們繼續。
首先下載spring security 3.1jar,地址:http://www.springsource.org/spring-community-download。我這里有曾今下載的,就不用了、jar結構如下:
紅色的呢,是源碼包,我們不用加入,藍色圈中的是兩個例子、你可以部署學習一下。其他的就是我們需要的jar,可以根據包名稱發現各個包都是一個spring security 的特性,一般來說我們把jar都加進去,隨着項目需要都會用到的。
接下來我們需要新建一個applicationContext-security.xml文件,這個是spring security 配置必須的一個文件。內容如下:
<?xml version="1.0" encoding="UTF-8"?> <b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <!-- 開啟默認的攔截器 --> <http auto-config='true'> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> </http> <!-- 權限管理者 --> <authentication-manager> <!-- 權限提供者 --> <authentication-provider> <!-- 可提供登陸訪問的用戶 --> <user-service> <user name="haha" password="haha" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="xixi" password="xixi" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </b:beans>
里面大概解釋了一下,其中http節點里面默認的開啟的幾個必須的攔截器,下面的user-service 就是可以登陸訪問的用戶列表,我們這里沒有用數據庫所以就這樣配置了,如果使用數據庫 配置一個dataSource即可,包括后面的authorities都是通過數據庫管理用戶權限的,這里我們暫時入門不做深入講解。
然后我們需要一個spring security 的過濾器配置、web.xml完整配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <!-- 應用上下文配置文件 --> <param-value>/WEB-INF/spring-servlet.xml,/WEB-INF/applicationContext-security.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- spring securit start --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring securit start --> <!-- 配置spring核心servlet --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- url-pattern配置為/,不帶文件后綴,會造成其它靜態文件(js,css等)不能訪問。如配為*.do,則不影響靜態文件的訪問 --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
其中springSecurityFilterChain 過濾器必須放在最前面,因為spring security的安全機制是保護在web最外層的安全框架,所以你的任何訪問都要經過spring security 投票機制授權才可以訪問的,否則不允許訪問。只有登陸用戶才可以訪問。
contextConfigLocation配置就是掃描我們的spring mvc和spring security配置文件。
具體完整的目錄結構如下:
下面我們啟動web看看會發生什么神奇的事情。下面我們訪問http://localhost:8080/SpringMVC/welcome
奇跡發生了,我們並沒有創建登陸頁面,那這個登陸頁面哪里來的呢?哈哈,不要着急,慢慢來講,看看url spring_security_login ,還記得我們前面配置的spring security 的配置文件的<http>這個配置默認會開啟幾個過濾器,其中有一個就是攔截發現我們沒登陸然后查找登陸頁面,但為什么自動出來呢?其是它為 我們默認了一個登陸頁面,登陸頁面我們可以指定一個,前面我們沒指定所以檢查發現沒有它就默認了一個登陸頁面給我們,下面我們登陸看看會發生什么情況。 (什么你不知道賬號密碼?其實就是我們spring security配置的那個賬號密碼)。
輸入賬號密碼結果:
跳轉到了我們剛剛要訪問的uri了,中間還會檢查我們的賬號是否有權,有權才會訪問成功,無權則會轉到無權訪問頁面。好了,到這里spring mvc+spring security 集成就完成了,剩下的工作就是一步一步的慢慢學習spring security 來使用更多的完善的功能。簡單吧,就這點東西。
到這里我們再試試如果登錄一個不存在的賬號會發生什么情況、我輸入了一個admin、結果出現如下圖:
spring security已經幫我們檢查了,賬號不存在,他會把我們繼續重定向到登錄頁面,知道登錄成功,否則你永遠都面對的是這個登錄頁面。
好了今天主要分享的就這點,師傅引進門修行靠個人。不過我想了想,還是再分享一點有用的、有的人會想如果我的登錄頁面需要自定義怎么辦?下面我們就講講。
首先自定義登陸,我們需要修改applicationContext-security.xml 配置文件,修改如下:
<!-- 開啟默認的攔截器 --> <http auto-config='true'> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 登陸頁面配置 --> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true"/> </http> <!-- 權限管理者 --> <authentication-manager> <!-- 權限提供者 --> <authentication-provider> <!-- 可提供登陸訪問的用戶 --> <user-service> <user name="haha" password="haha" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="xixi" password="xixi" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
其中就多加 了一個form 配置節點,從命名可以看出login-page就是你的登陸頁面,default-target-url是默認的登陸成功后的頁 面,authentication-failure-url就是當你輸入非法賬號或者密碼自動重定向到login.jsp.
接下來創建我們自定義的登陸頁面,我的就是login.jsp,有人到這里會想,form接下來該如何寫呢?怎么寫才能被攔截呢?如下:
<h1>user login</h1> <form action="j_spring_security_check" method="post"> 用戶名<input type="text" name="j_username"/><br/> 密碼<input type="password" name="j_password"/><br/> <input type="submit" value="submit"/> </form>
action="j_spring_security_check"必須這樣寫,否則攔截器攔截不到。登陸的字段j_username j_password必須這樣寫,否則你的登陸攔截器獲取不到value。當然你也可以自定義,但前提是你必須繼承 UsernamePasswordAuthenticationFilter 過濾器去重寫一下,這里我們就不麻煩了,而且一般情況下我們不需要重寫,就用它提供的即可。好了,到這里我們可以啟動服務器了。我們再次訪問:http://localhost:8080/SpringMVC/welcome看看會發生神馬變化。如圖:
咦?這是什么情況?url變了,是我們要訪問的登陸地址。可是頁面的登陸form呢?不要着急,這種情況我當時見多了,第一反應login.jsp 沒有被放行,攔截下來了、受保護的資源。前面我們不是講過spring security 是保護在web最外層的嘛,訪問任何資源需要投票,授權才能訪問的,這個也不例外。
好了,知道神馬情況了,我們修改吧!修改如下部分片段即可:
<!-- 開啟默認的攔截器 --> <http auto-config='true'> <!--對login.jsp放行,不用保護--> <intercept-url pattern="/login.jsp" filters="none" /> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 登陸頁面配置 --> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true"/> </http>
然后我們啟動服務器再次訪問http://localhost:8080/SpringMVC/welcome
不幸的事情又發生了,控制台報錯,服務器啟動失敗!如下圖:
其實大概的意思是講下面的這個配置作廢了。
<!--對login.jsp放行,不用保護-->
<intercept-url pattern="/login.jsp" filters="none" />這個配置是spring security 2.X中的,3.X以后作廢了,使用新的方式了。但最起碼你讓我不能再次調用撒,這樣我就知道沒有這個標簽了,可以理解的是,廢棄相關配置要耗費很大的精 力,動一發而牽全身,所以它還可以調用,但是運行的時候就不能。不過錯誤告訴我們怎么使用新的標簽了,就是新建一個節點標簽,屬性 security="none" 來放行,好了,我們修改一下。修改部分配置如下:
<!-- spring securit 3.X新的資源放行配置方式,不受保護的資源 --> <http pattern="/login.jsp" security="none"/> <!-- 開啟默認的攔截器 --> <http auto-config='true'> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 登陸頁面配置 --> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true"/> </http>
在http節點上面再加一個節點,然后配置不需要攔截的。pattern屬性的意思就是通過正則表達式來匹配的。security="none"就 是不安全的,意思就是不受spring security保護的資源,這里還要提一點,就是.jpg、.gif、.swf、.css、.js/等等資源文件都會被攔截下來,即使他是包含在一個已 經放行的jsp頁面或者uri的request、怎么理解?就是比如:我們的login.jsp放行了,但是我們沒有放行.jpg這樣的圖片資源,當我們 訪問login.jsp的時候圖片是不顯示的,因為它沒有被放行,從這里可以看出spring security是非常嚴格的檢查機制。假如我們要放行那些怎么辦?
spring security 2.X中配置如下:
<http auto-config='true'> <!-- public 資源文件 –> <intercept-url pattern="/**/*.jpg" filters="none" /> <intercept-url pattern="/**/*.png" filters="none" /> <intercept-url pattern="/**/*.gif" filters="none" /> <intercept-url pattern="/**/*.ico" filters="none" /> <intercept-url pattern="/**/*.css" filters="none" /> <intercept-url pattern="/**/*.js" filters="none" /> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 登陸頁面配置 --> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true"/> </http>
當然我們這里講spring security 3.X,所以3.X的如下:
<http pattern="/**/*.jpg" security="none"/> <http pattern="/**/*.png" security="none"/> <http pattern="/**/*.gif" security="none"/> <http pattern="/**/*.ico" security="none"/> <http pattern="/**/*.css" security="none"/> <http pattern="/**/*.js" security="none"/> <!-- spring securit 3.X新的資源放行配置方式,不受保護的資源 --> <http pattern="/login.jsp" security="none"/> <http auto-config='true'> <!-- 允許訪問的uri --> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 登陸頁面配置 --> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true"/> </http>
上面的pattern="/**/*.jpg" 配置意思就是放行,項目中所有的.jpg資源,以后的以此類推的原理。你亦可以放行某一個文件下的,具體就是正則表達式的配置。
好了,我們還是回到剛剛修改的放行資源試試,再次啟動服務器訪問:http://localhost:8080/SpringMVC/welcome
當我們再次訪問的時候login.jsp已經出來了、這個時候我們登陸,成功后直接跳轉到/welcome 的響應頁面。結果如圖;
這里我們沒有配置用戶資源訪問權限,所以訪問的資源直接可以訪問,如果配置了訪問權限登陸成功后,spring security還會檢查是否有權訪問,無權重定向。
好了到這里,今天分享的入門到此完畢。后面有時間再慢慢分享,這個框架還是很值得學習的。功能比較強大,官方文檔比較全面,可以好好研讀一下,感謝抽寶貴的時間閱讀。
轉自:http://www.cnblogs.com/Beyond-bit/p/springmvc_and_springsecurity.html