Spring Security实现后台管理员登录(一)

一、实现功能

 

二、数据表设计

为了测试方便,这里创建一个简单的数据表,只含有name和password两个字段。至于角色,权限等,这里都先不考虑。

插入一条数据,name为admin,password为e10adc3949ba59abbe56e057f20f883e(这是123456经md5加密后得到的值)。

 

三、配置文件

1 在pom.xml中添加三个相关的包

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <dependency>  
  2.     <groupId>org.springframework.security</groupId>  
  3.     <artifactId>spring-security-core</artifactId>  
  4.     <version>${org.springframework.security.version}</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.springframework.security</groupId>  
  8.     <artifactId>spring-security-config</artifactId>  
  9.     <version>${org.springframework.security.version}</version>  
  10. </dependency>  
  11. <dependency>  
  12.     <groupId>org.springframework.security</groupId>  
  13.     <artifactId>spring-security-web</artifactId>  
  14.     <version>${org.springframework.security.version}</version>  
  15. </dependency>  

 

2 web.xml中添加过滤器

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <!-- 添加Spring-Security过滤器 -->  
  2. <filter>  
  3.     <filter-name>springSecurityFilterChain</filter-name>  
  4.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5. </filter>  
  6. <filter-mapping>  
  7.     <filter-name>springSecurityFilterChain</filter-name>  
  8.     <url-pattern>/service/*</url-pattern>  
  9. </filter-mapping>  
  

 

3 src/main/resource/spring/applicationContext-security.xml的内容为

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans:beans xmlns:beans="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns="http://www.springframework.org/schema/security"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans     
  6.             http://www.springframework.org/schema/beans/spring-beans-3.2.xsd    
  7.             http://www.springframework.org/schema/security     
  8.             http://www.springframework.org/schema/security/spring-security-3.1.xsd">  
  9.       
  10.     <!-- 需要登陆能够访问的路径 -->     
  11.     <http access-denied-page="/service/login/unSecurity" entry-point-ref="authenticationProcessingFilterEntryPoint">  
  12.         <!-- 首页 -->  
  13.         <intercept-url pattern="/service/index/index" access="ROLE_AUTHORITY"/>             
  14.       
  15.         <!-- 自定义loginFilter -->  
  16.         <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />  
  17.         <logout logout-url="/service/login/logout" logout-success-url="/" invalidate-session="true"  
  18.                 delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE"/>  
  19.         <session-management invalid-session-url="/service/login/unSecurity" session-authentication-strategy-ref="sas"/>  
  20.     </http>  
  21.       
  22.     <!-- 登录验证器 -->  
  23.     <beans:bean id="loginFilter" class="com.zheng.shared.security.JadeUserPwdAuthFilter">  
  24.         <!-- 处理登录的action -->  
  25.         <beans:property name="filterProcessesUrl" value="/service/login/userLogin"/>  
  26.         <!-- 认证管理 点击完登录后,最终实现校验的是AuthenticationProvider-->  
  27.         <beans:property name="authenticationManager" ref="myAuthenticationManager"/>  
  28.         <!-- 验证成功后的处理-->  
  29.         <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"/>  
  30.         <!-- 验证失败后的处理-->  
  31.         <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"/>  
  32.           
  33.         <!-- 实现多个帐号登录时最后一次登录的有效,目前只请允许登录一个帐号 -->  
  34.         <beans:property name="sessionAuthenticationStrategy" ref="sas"/>  
  35.     </beans:bean>  
  36.     <beans:bean id="loginLogAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">  
  37.         <beans:property name="alwaysUseDefaultTargetUrl" value="true"/>  
  38.         <beans:property name="defaultTargetUrl" value="/service/login/loginSucc"/>  
  39.     </beans:bean>  
  40.     <beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">  
  41.         <!-- 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sendRedirect -->  
  42.         <beans:property name="defaultFailureUrl" value="/service/login/loginFail"/>  
  43.     </beans:bean>  
  44.     <beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">    
  45.         <beans:property name="maximumSessions" value="1"/>  
  46.         <beans:property name="exceptionIfMaximumExceeded" value="false"/>    
  47.         <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>    
  48.     </beans:bean>  
  49.     <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>  
  50.     <authentication-manager alias="myAuthenticationManager">  
  51.         <authentication-provider ref="authenticationProvider"/>  
  52.     </authentication-manager>  
  53.     <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">  
  54.         <!-- 配置异常能被捕捉 -->  
  55.         <beans:property name="hideUserNotFoundExceptions" value="false" />  
  56.           
  57.         <beans:property name="userDetailsService" ref="userDetailService" />   
  58.         <!-- <beans:property name="messageSource" ref="messageSource" /> -->  
  59.         <!-- <beans:property name="userCache" ref="userCache" />可使用缓存保存用户信息-->  
  60.         <!-- 开发过程中可以先把这两行注释掉-->  
  61.         <!-- <beans:property name="passwordEncoder" ref="passwordEncode"/>  
  62.         <beans:property name="saltSource" ref="saltSource" />  -->  
  63.     </beans:bean>  
  64.     <!-- 密码加密 -->  
  65.     <beans:bean id="passwordEncode" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />    
  66.     <beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">    
  67.         <beans:property name="userPropertyToUse" value="id"/>    
  68.     </beans:bean>  
  69.     <beans:bean id="userDetailService" class="com.zheng.service.impl.UserServiceImpl" />  
  70.     <!-- 未登录的切入点-->  
  71.     <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  
  72.         <beans:property name="loginFormUrl" value="/service/login/unSecurity" />  
  73.     </beans:bean>  
  74.        
  75. </beans:beans>  

 

四、相关代码

1src/main/Java/com/zheng/shared/sercurity/JadeUserPwdAuthFilter.java中的代码为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.zheng.shared.security;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.springframework.beans.factory.annotation.Autowired;  
  7. import org.springframework.security.authentication.AuthenticationServiceException;  
  8. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;  
  9. import org.springframework.security.core.Authentication;  
  10. import org.springframework.security.core.AuthenticationException;  
  11. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  
  12.   
  13. import com.zheng.bean.User;  
  14. import com.zheng.dao.UserMapper;  
  15.   
  16. public class JadeUserPwdAuthFilter extends UsernamePasswordAuthenticationFilter {  
  17.   
  18.       
  19.     public static final String USERNAME = "userName";  
  20.     public static final String PASSWORD = "userPassword";  
  21.       
  22.     @Autowired  
  23.     private UserMapper userDao;  
  24.       
  25.     @Override  
  26.     public Authentication attemptAuthentication(HttpServletRequest request,  
  27.             HttpServletResponse response) throws AuthenticationException {  
  28.         if (!request.getMethod().equals("POST")) {  
  29.             throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());  
  30.         }  
  31.           
  32.         String userName = request.getParameter(USERNAME);  
  33.         String password = request.getParameter(PASSWORD);  
  34.   
  35.         User user = userDao.findUserByUserName(userName);  
  36.         System.out.println("username: " + user.getUsername());  
  37.         System.out.println("password: " + user.getPassword());  
  38.           
  39.         // 验证用户是否被启用  
  40.         UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(userName, password);  
  41.         // 允许子类设置详细属性    
  42.         setDetails(request, authRequest);  
  43.         // 运行UserDetailsService的loadUserByUsername 再次封装Authentication   
  44.         return this.getAuthenticationManager().authenticate(authRequest);  
  45.     }  
  46. }  

 

2 src/main/java/com/zheng/service/UserService.java的内容为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.zheng.service;  
  2.   
  3. import org.springframework.security.core.userdetails.UserDetailsService;  
  4.   
  5. public interface UserService extends UserDetailsService{  
  6.   
  7. }  

 

3 src/main/java/com/zheng/service/impl/UserServiceImpl.java的内容为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.zheng.service.impl;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.security.core.userdetails.UserDetails;  
  5. import org.springframework.security.core.userdetails.UsernameNotFoundException;  
  6.   
  7. import com.zheng.bean.User;  
  8. import com.zheng.dao.UserMapper;  
  9. import com.zheng.service.UserService;  
  10.   
  11.   
  12. public class UserServiceImpl implements UserService{  
  13.   
  14.     @Autowired  
  15.     private UserMapper userMapper;  
  16.       
  17.     @Override  
  18.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
  19.         User user = null;  
  20.         try {  
  21.             user = userMapper.findUserByUserName(username);  
  22.         } catch (Exception e) {  
  23.             e.printStackTrace();  
  24.         }  
  25.         if (user == null) {  
  26.             throw new UsernameNotFoundException("用户名或密码不正确!");  
  27.         }  
  28.         System.out.println("username: " + user.getUsername());  
  29.         System.out.println("password: " + user.getPassword());  
  30.           
  31.         return user;  
  32.     }  
  33.   
  34. }  

 

4 src/main/java/com/zheng/bean/User.java的内容为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.zheng.bean;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Collection;  
  5.   
  6. import org.springframework.security.core.GrantedAuthority;  
  7. import org.springframework.security.core.userdetails.UserDetails;  
  8.   
  9. public class User implements UserDetails , Serializable {  
  10.     private static final long serialVersionUID = 123L;  
  11.       
  12.     private String userName;  
  13.   
  14.     private String password;  
  15.       
  16.     private Collection<GrantedAuthority> authorities;// 用户证书是否有效  
  17.           
  18.     @Override  
  19.     public String getUsername() {  
  20.         return this.userName;  
  21.     }  
  22.   
  23.     @Override  
  24.     public String getPassword() {  
  25.         return password;  
  26.     }  
  27.       
  28.     public void setPassword(String password) {  
  29.         this.password = password;  
  30.     }  
  31.       
  32.     @Override  
  33.     public Collection<? extends GrantedAuthority> getAuthorities() {  
  34.         return authorities;  
  35.     }  
  36.       
  37.     public void setAuthorities(Collection<GrantedAuthority> authorities) {  
  38.         this.authorities = authorities;  
  39.     }  
  40.       
  41.     @Override  
  42.     public boolean isAccountNonExpired() {  
  43.         return true;  
  44.     }  
  45.   
  46.     @Override  
  47.     public boolean isAccountNonLocked() {  
  48.         return true;  
  49.     }  
  50.       
  51.     @Override  
  52.     public boolean isCredentialsNonExpired() {  
  53.         return true;  
  54.     }  
  55.   
  56.     @Override  
  57.     public boolean isEnabled() {  
  58.         return true;  
  59.     }  
  60. }  

 

特别需要注意的是:用户只有在不过期、没被锁定、没被禁用的情况下才能登录成功,所以isEnabled()方法的返回值设为真,表示用户没有禁用。

 

5 src/main/java/com/zheng/dao/UserMapper.java的内容为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.zheng.dao;  
  2.   
  3. import com.zheng.bean.User;  
  4.   
  5. public interface UserMapper {  
  6.     /** 
  7.      * 根据用户名查找 
  8.      * @param userName 
  9.      * @return 
  10.      */  
  11.     User findUserByUserName(String name);  
  12. }  

 

6 src/main/resources/config/mybatis/mapper/UserMapper.xml

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >  
  3. <mapper namespace="com.zheng.dao.UserMapper" >  
  4.   <resultMap id="BaseResultMap" type="com.zheng.bean.User" >  
  5.      <result column="name" property="userName" jdbcType="VARCHAR" />  
  6.      <result column="password" property="password" jdbcType="VARCHAR" />  
  7.   </resultMap>  
  8.     
  9.   <select id="findUserByUserName" parameterType="string" resultMap="BaseResultMap" >  
  10.     select * from user where name = #{userName}  
  11.   </select>  
  12.   
  13. </mapper>  

 

7 LoginController.java中响应登录成功和失败的方法为

 

[java] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 登陆成功进行处理的方法 
  3.  * @param request 
  4.  * @return 
  5.  */  
  6. @RequestMapping("/loginSucc")  
  7. @ResponseBody  
  8. public Map<String,Object> loginSucc(HttpServletRequest request){  
  9.     System.out.println("登录成功!");  
  10.     Map<String,Object> result = new HashMap<String,Object>();  
  11.     return result;  
  12. }  
  13.   
  14. /** 
  15.  * 登陆失败进行的操作 
  16.  * @param request 
  17.  * @return 
  18.  */  
  19. @RequestMapping("/loginFail")  
  20. @ResponseBody  
  21. public Map<String,Object> loginFail(HttpServletRequest request){  
  22.     System.out.println("登录失败!");  
  23.     Map<String,Object> result = new HashMap<String,Object>();  
  24.     return result;  
  25. }  

 

五、运行结果

 

 
posted @ 2017-04-19 12:40  爱你爱自己  阅读(9958)  评论(0编辑  收藏  举报