(轉)Spring Security 3.1 自定義實例之登陸


Spring Security 3.1 自定義實例之登陸

Spring Security的前身是Acegi,功能強大,配置也比較復雜,我也是新手,先通過動手實現一個登陸驗證實例來進入Spring Security的世界吧!
1.准備:
下載Spring Security:官方下載地址: http://www.springsource.org/spring-security 在下載之前Spring會要你填寫一些基本信息,然后就會自動跳轉到下載地址, 目前最新版本為spring-security-3.1.0.RELEASE,解壓后在dist目錄下可以看到:
其中兩個War包是實例,*-source.jar是源代碼
將dist中的Jar包全部導入到工程中,如圖:
 
2.修改web.xml,插入以下代碼
[html]  view plain copy print ?
  1.   <filter>  
  2.      <filter-name>springSecurityFilterChain</filter-name>  
  3.      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  4.   </filter>  
  5.   
  6.    <filter-mapping>  
  7.      <filter-name>springSecurityFilterChain</filter-name>  
  8.      <url-pattern>/*</url-pattern>  
  9.    </filter-mapping>  
修改context-param項,目的就是帶起接下來要新建的AppSecurity.xml(名字隨意)
[html]  view plain copy print ?
  1. <context-param>   
  2.   <param-name>contextConfigLocation</param-name>   
  3.   <param-value>classpath*:App*.xml</param-value>  
  4. </context-param>  

3.新建AppSecurity.xml,如下:
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans:beans xmlns="http://www.springframework.org/schema/security"  
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
 4     xmlns:beans="http://www.springframework.org/schema/beans"  
 5     xsi:schemaLocation="
 6        http://www.springframework.org/schema/beans
 7        http://www.springframework.org/schema/beans/spring-beans.xsd
 8        http://www.springframework.org/schema/security
 9        http://www.springframework.org/schema/security/spring-security-3.1.xsd">
10       
11     <http auto-config="true">
12         <intercept-url pattern="/*" access="ROLE_USER" />
13     </http>
14 
15     <authentication-manager alias="authenticationManager">
16         <authentication-provider>
17             <user-service>
18                 <user name="test" password="test" authorities="ROLE_USER" />
19             </user-service>
20         </authentication-provider>
21            
22     </authentication-manager>
23 </beans:beans>

 

 
這個xml文件里用了Spring Security的最簡單配置 <http auto-config="true"/>含義就是使用Spring Security自動為我們設置一些參數,然后聲明了訪問所有URL都需要為ROLE_USER,然后在authentication-manager用硬編碼的形式定義了一個用戶test,權限為ROLE_USER,運行這個實例應該可以看到這樣的登錄界面:
這個界面就是Spring Security為我們提供的登陸界面;
上面這個實例太簡單了,在現實項目中基本不會這么用,比如項目如有如下需求:
1.自定義登錄界面;
2.用Ajax方式登錄驗證;
3.用數據庫記錄用戶信息,進行登錄驗證;
4.用MD5方式密碼加密;
OK 接下來我們先來看看 自定義登錄界面的配置實例吧!
1.修改AppSecurity.xml中的http項,如下:
1     <http auto-config="true">
2         <intercept-url pattern="/login.jsp" filters="none" />
3         <intercept-url pattern="/*" access="ROLE_USER" />
4         <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/index.jsp"/>
5     </http> 
login-page:當用戶登錄時顯示自定義登錄頁面 
authentication-failure-url:登錄失敗時跳轉到哪個頁面 
default-target-url:登錄成功后跳轉到哪個頁面 
這樣就把默認的登錄界面指向了login.jsp了,並且配置了出錯后的指向路徑和默認跳轉路徑等信息,當然這里的login.jsp需要任何人都可以訪問,不然的話會造成循環調用
2.設計login.jsp,關鍵代碼如下:
[html]  view plain copy print ?
  1. <html>  
  2. <head>  
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  4. <title>登陸界面</title>  
  5. </head>  
  6. <body>  
  7. <h3>歡迎登陸</h3>  
  8. <form action='/ctosii_middle/j_spring_security_check' method='POST'>  
  9.  <table>  
  10.     <tr><td>用戶名:</td><td><input type='text' name='j_username' value=''></td></tr>  
  11.     <tr><td>密    碼:</td><td><input type='password' name='j_password'/></td></tr>  
  12.     <tr><td colspan='2'><input name="submit" type="submit" value="登陸"/></td></tr>  
  13.   </table>  
  14. </form>  
  15. </body>  
  16. </html>  
大家可以看到這里的action指向了j_spring_security_check,這個路徑也是Spring Security為我們自動生成的,這里需要post的兩個個參數為 j_username,j_password,運行這個實例可以看到如下登陸界面:
2.用ajax的方式實現的登錄驗證
Spring Security默認的是登陸驗證通過用跳轉的方式,但是在實際應用中很多應用的登錄界面需要用到ajax的方式來實現登陸驗證
1.修改AppSecurity.xml中的http項,如下:
1     <http auto-config="true">
2         <intercept-url pattern="/login**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
3         <intercept-url pattern="/**/*.js" access="IS_AUTHENTICATED_ANONYMOUSLY" />
4         <intercept-url pattern="/**" access="ROLE_USER" />
5         <form-login login-page="/login.jsp" authentication-failure-url="/login_fail.do" default-target-url="/login_success.do"/>
6     </http> 

這里配置了兩個路徑失敗后的調用路徑和成功后的調用路徑。利用這兩個路徑可以實現ajax登陸。
在login_fail.do和login_success.do中可以輸出登陸失敗、成功的消息

2.Login.jsp修改如下:

 1 <html>
 2 <head>
 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 4 <script type="text/javascript" src="js/jquery-last.min.js"></script>
 5 <script type="text/javascript">
 6 function doLogin(){
 7     var url = "/ctosii_middle/j_spring_security_check";
 8     var username= $("input[name='j_username']").val();
 9     var password= $("input[name='j_password']").val();
10     $.ajax({
11         url:url,
12         type:"POST",
13         data:"j_username="+username+"&j_password="+password,
14         success: function(data){
15             $("#results").text(data);
16           }
17     });
18 }
19 </script>
20 
21 
22 <title>登陸界面</title>
23 </head>
24 <body>
25 <h3>歡迎登陸</h3>
26 <form>
27  <table>
28     <tr><td>用戶名:</td><td><input type='text' name='j_username' value=''></td></tr>
29     <tr><td>密    碼:</td><td><input type='password' name='j_password'/></td></tr>
30     <tr><td colspan='2'><input name="submit" type="button" onclick="doLogin()" value="登陸"/></td></tr>
31   </table>
32   <div id="results"></div>
33 </form>
34 </body>
35 </html>

3.用數據庫記錄用戶信息,進行登錄驗證

上面的兩個例子都是用了硬編碼的方式驗證用戶信息,而實際項目中肯定是會把用戶信息存到數據庫中的,最典型的就是建users,role,user_role這三張表:

users:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) CHARACTER SET utf8 NOT NULL,
  `password` varchar(100) NOT NULL,
  `enabled` varchar(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

role:

1 DROP TABLE IF EXISTS `role`;
2 CREATE TABLE `role` (
3   `id` int(11) NOT NULL AUTO_INCREMENT,
4   `name` varchar(100) CHARACTER SET utf8 NOT NULL,
5   `description` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
6   `enabled` tinyint(1) DEFAULT NULL,
7   PRIMARY KEY (`id`),
8   UNIQUE KEY `rolename_index` (`name`) USING BTREE
9 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

user_role:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) CHARACTER SET utf8 NOT NULL,
  `password` varchar(100) NOT NULL,
  `enabled` varchar(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

然后執行Sql插入數據:

INSERT INTO `users` VALUES ('0', 'xiakan', 'xiakan', '1');
INSERT INTO `role` VALUES ('1', 'user', '用戶角色', 1);
INSERT INTO `role` VALUES ('2', 'admin', '管理員角色', 1);
INSERT INTO `user_role` VALUES ('1', '1', '0');

2.修改AppSecurity.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans:beans xmlns="http://www.springframework.org/schema/security"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:beans="http://www.springframework.org/schema/beans"
 5        xsi:schemaLocation="
 6        http://www.springframework.org/schema/beans
 7        http://www.springframework.org/schema/beans/spring-beans.xsd
 8        http://www.springframework.org/schema/security
 9        http://www.springframework.org/schema/security/spring-security-3.1.xsd">
10     
11     <http auto-config="true">
12         <intercept-url pattern="/login**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
13         <intercept-url pattern="/**/*.js" access="IS_AUTHENTICATED_ANONYMOUSLY" />
14         <intercept-url pattern="/**" access="ROLE_USER" />
15         <form-login login-page="/login.jsp" authentication-failure-url="/login_fail.do" default-target-url="/login_success.do"/>
16     </http>
17       
18     <beans:bean id="userDetailsService" class="com.xk.security.UserDetailServiceImpl" />
19     
20     <authentication-manager alias="authenticationManager">
21         <authentication-provider user-service-ref="userDetailsService" />
22     </authentication-manager>
23 </beans:beans>

我們添加了一個Bean:com.xk.security.UserDetailServiceImpl,這個bean的代碼如下:

 1 package com.xk.security;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.security.core.GrantedAuthority;
 8 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 9 import org.springframework.security.core.userdetails.UserDetails;
10 import org.springframework.security.core.userdetails.UserDetailsService;
11 import org.springframework.security.core.userdetails.UsernameNotFoundException;
12 
13 import com.xk.dao.IUserManager;
14 import com.xk.item.Role;
15 import com.xk.item.User;
16 
17 public class UserDetailServiceImpl implements UserDetailsService{
18     @Autowired
19     private IUserManager userManager = null;
20     public UserDetailServiceImpl(){
21     }
22     public IUserManager getUserManager() {
23         return userManager;
24     }
25     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
26         User user = userManager.search(username);
27         if  (user==null)
28             throw new UsernameNotFoundException(username+" not exist!");
29         List<GrantedAuthority> authsList = new ArrayList<GrantedAuthority>();
30         for  (Role role:userManager.getRoles(user)) {
31             authsList.add(new SimpleGrantedAuthority(role.getName()));
32         }
33         boolean accountNonExpired = true;
34         boolean credentialsNonExpired = true;
35         boolean accountNonLocked = true;
36 
37         UserDetails userdetails = new org.springframework.security.core.userdetails.User(user.getUsername(), user
38                 .getPassword(),user.isEnabled(), accountNonExpired, credentialsNonExpired, accountNonLocked, authsList);
39 
40         return userdetails;
41     }
42 }

用剛剛的insert到數據庫的用戶信息,就可以看到如下界面:

4.用MD5方式密碼加密;

 
這里的數據庫中用了明碼的方式來存儲用戶密碼,這樣對用戶來說是很不安全的,前段時間各大網站的密碼泄露事件就是因為用了明文存儲用戶密碼,為了加密用戶的密碼,這里我們可以用MD5的方式:
1.修改AppSecurity.xml:
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailsService">
            <password-encoder hash="md5">
                <salt-source user-property="username" />
            </password-encoder>
        </authentication-provider>
    </authentication-manager>
並將xiakan的密碼改成65aedbe7fb37dc0b2a0da914fb905328
其實也可以用js做好加密后post到服務器,這樣更安全!


免責聲明!

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



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