spring-cecurity的簡介:
Spring Security是一個能夠為基於Spring的企業應用系統提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,為應用系統提供聲明式的安全訪問控制功能,減少了為企業系統安全控制編寫大量重復代碼的工作。
本博客包含的功能:
1)使用基本的spring-security demo的實現,采用spring-security默認的登錄
2)在spring-security的基礎上自定義登錄頁面以及注銷功能
3)使用spring-security數據庫中獲取數據進行登錄驗證
4)使用spring-decurity的BCrypt對密碼進行加密處理
1.新建一個war包類型的maven項目
注:新建的maven工程需要轉換為Web工程的方法和項目的pom.xml中報錯:web.xml is missing and <failOnMissingWebXml> is set to true 解決方法請看:
https://www.cnblogs.com/sun-flower1314/p/11732915.html
2.在pom.xml中加入Spring Security的maven配置
<properties> <spring.version>4.2.4.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.1.0.RELEASE</version> </dependency> </dependencies> <build> <plugins> <!-- java編譯插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- 指定端口 --> <port>9080</port> <!-- 請求路徑 --> <path>/</path> </configuration> </plugin> </plugins> </build>
3.在/src/main/resources下新建spring-security.xml的配置文件。
該配置文件與以往的稍有不同,需要注意的點有:
以往的前綴<beans ></beans>是直接這樣,是默認為beans
現在的為<beans:beans > </beans:beans>,默認的xmlns為security的,因為這里使用的基本都是以<security:xxx >開頭,為了省去麻煩,所以將security配置為默認的。
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="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.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login /> </http> <!-- 認證管理器 --> <authentication-manager> <authentication-provider> <user-service> <user name="admin" password="123456" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
spring-security.xml配置文件中屬性說明:
<1> <http >標簽中:屬性use-expressions 表示是否啟動SPEL表達式 false表示不啟用,若不配置use-expressions屬性,則在子標簽intercept-url中需配置access=hasRole('ROLE_USER')
<2><intercept-url>表示攔截url,其屬性pattern="/*" 表示只攔截根目錄下的資源,不包括子目錄中的資源, /** 攔截所有資源; 屬性access表示配置角色名稱 其值必須是【ROLE_】開頭
<3><form-login /> 表示開啟表單功能
<4><authentication-provider> 表示認證提供者
<5><user >標簽配置當前系統的登錄用戶:用戶名 name; 密碼 password; 當前用戶所屬角色 authorities
4.配置web.xml文件,整個文件為:
其中包含加載了classpath:spring-security.xml文件以及加入了一個安全過濾器,其中的springSecurityFilterChain為固定名稱,不能改變
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-security.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 安全過濾器 --> <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> </web-app>
5. 然后啟動用maven命令啟動項目,tomcat7:run ,啟動成功后,在瀏覽器中輸入地址訪問,即使沒有寫任何界面,也可看到security默認的登錄界面:
6.輸入用戶名和密碼,若輸入錯誤的用戶名和密碼,可看到如下界面:
輸入正確用戶密碼登錄后,會顯示404錯誤,因為沒有配置默認的首頁,在webapp下配置index.html頁面即可。
7.用戶自定義登錄頁
實際開發中,不可能使用系統的默認登錄頁
1)構建登錄頁
①form表單中規定 action=“/login" method="post"
②<input >輸入用戶規定的 name="username";輸入密碼框規定name="password"
即如下所示:
<form action='/login' method='POST'> <table> <tr> <td>用戶名:</td> <td><input type='text' name='username' value=''></td> </tr> <tr> <td>密碼:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="登陸" /></td> </tr> </table> </form>
2)構建登陸失敗頁 login_error.html(內容略)
3)再次修改spring-security.xml的配置文件
增加配置說明如下:
<1>login-page:指定登錄頁面。
<2>authentication-failure-url:指定了身份驗證失敗時跳轉到的頁面。
<3>default-target-url:指定了成功進行身份驗證和授權后默認呈現給用戶的頁面。
<4>csrf disabled="true" 關閉csrf
<5><headers><frame-options policy="SAMEORIGIN"/> </headers> 表示在頁面中還存在iframe標簽嵌入其他頁面
<6><logout/> 表示注銷退出,並且在注銷按鈕中配置的action為:/logout
<!-- 以下頁面不被攔截 -->
<http pattern="/login.html" security="none"></http>
<http pattern="/login_error.html" security="none"></http>
<!-- 頁面攔截規則 -->
<http use-expressions="false">
<intercept-url pattern="/*" access="ROLE_USER" />
<form-login login-page="/login.html" default-target-url="/index.html" authentication-failure-url="/login_error.html" always-use-default-target="true" />
<csrf disabled="true"/>
<!-- <headers>
<frame-options policy="SAMEORIGIN"/>
</headers> -->
<logout/>
</http>
其中security="none"表示次資源不被攔截,若未設置登錄頁,則會出現以下錯誤
csrf disabled="true" 關閉csrf ,如果不加會出現錯誤,CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。
8、從數據庫中匹配用戶名和密碼,而不用配置文件中的用戶名和密碼
1)編寫驗證實現類,即繼承Security自帶的接口UserDetailsService
LoginCheck.java
package com.hxc.securityDemo; import java.util.ArrayList; import java.util.List; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; public class LoginCheck implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //1.構建角色列表 List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(); grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); String password = "123456"; //2.從數據庫中查詢數據進行檢驗 // TbUser tbUser = userService.findOne(username); // if(tbUser == null) { // return null; // } // password = tbUser.getPassword(); //... //new User 為Security包中的類,其中第一個參數為登錄界面輸入的用戶名,第二個為后台參數的密碼(即從數據庫中查詢),第三個為權限角色 return new User(username, password, grantedAuthorities); } }
2)在spring-security.xml配置文件中 將認證管理 修改為如下:
<authentication-manager>
<authentication-provider user-service-ref="userDetailService">
</authentication-provider>
</authentication-manager>
<beans:bean id="userDetailService" class="com.hxc.securityDemo.LoginCheck"></beans:bean>
9.自定義密碼加密處理
對於存入數據庫中密碼,不能顯示成明文,而需要經過加密處理。而傳統的MD5加密算法,雖然時不可逆算法加密,但可以在網上的彩虹表破解得到,因為其對同一密碼MD5加密后生成的都是同一密碼,固定不變。若采用BCrypt加密,即使時同一密碼,其加密后得到的密碼也是不同的。其原理是會先使用一個特定的字符串(如域名)加密,再使用一個隨機的salt(鹽值)加密。特定字符串是程序代碼中固定的,salt是每個密碼單獨隨機,混入最終加密后的密碼,驗證時也無需單獨提供之前的salt,從而無需單獨處理salt問題。
對於在項目中添加用戶時密碼處理如下:
public boolean add(TbUser user) { String userPassword = user.getPassword(); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encPassword = passwordEncoder.encode(userPassword); // System.out.println(encPassword); //存入數據庫中.... //..... // return true; }
用戶登錄驗證時,在spring-security.xml中的認證管理配置如下:
<beans:bean id="userDetailService" class="com.hxc.securityDemo.LoginCheck" /> <beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref='userDetailService'> <password-encoder ref="bcryptEncoder"></password-encoder> </authentication-provider> </authentication-manager>
自此 自定義配置完成