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

一、实现功能

 

二、数据表设计

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

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


三、配置文件

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

	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-core</artifactId>
		<version>${org.springframework.security.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-config</artifactId>
		<version>${org.springframework.security.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-web</artifactId>
		<version>${org.springframework.security.version}</version>
	</dependency>

2 web.xml中添加过滤器

	<!-- 添加Spring-Security过滤器 -->
	<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>/service/*</url-pattern>
	</filter-mapping>
  

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

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  
            http://www.springframework.org/schema/security   
            http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	
	<!-- 需要登陆能够访问的路径 -->   
	<http access-denied-page="/service/login/unSecurity" entry-point-ref="authenticationProcessingFilterEntryPoint">
		<!-- 首页 -->
		<intercept-url pattern="/service/index/index" access="ROLE_AUTHORITY"/>			
	
		<!-- 自定义loginFilter -->
		<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />
		<logout logout-url="/service/login/logout" logout-success-url="/" invalidate-session="true"
				delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE"/>
		<session-management invalid-session-url="/service/login/unSecurity" session-authentication-strategy-ref="sas"/>
	</http>
	
	<!-- 登录验证器 -->
	<beans:bean id="loginFilter" class="com.zheng.shared.security.JadeUserPwdAuthFilter">
		<!-- 处理登录的action -->
		<beans:property name="filterProcessesUrl" value="/service/login/userLogin"/>
		<!-- 认证管理 点击完登录后,最终实现校验的是AuthenticationProvider-->
		<beans:property name="authenticationManager" ref="myAuthenticationManager"/>
		<!-- 验证成功后的处理-->
		<beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"/>
		<!-- 验证失败后的处理-->
		<beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"/>
		
		<!-- 实现多个帐号登录时最后一次登录的有效,目前只请允许登录一个帐号 -->
		<beans:property name="sessionAuthenticationStrategy" ref="sas"/>
	</beans:bean>
	<beans:bean id="loginLogAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
		<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
		<beans:property name="defaultTargetUrl" value="/service/login/loginSucc"/>
	</beans:bean>
	<beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<!-- 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sendRedirect -->
		<beans:property name="defaultFailureUrl" value="/service/login/loginFail"/>
	</beans:bean>
	<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">  
	    <beans:property name="maximumSessions" value="1"/>
	    <beans:property name="exceptionIfMaximumExceeded" value="false"/>  
	    <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>  
	</beans:bean>
	<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
	<authentication-manager alias="myAuthenticationManager">
		<authentication-provider ref="authenticationProvider"/>
	</authentication-manager>
	<beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
		<!-- 配置异常能被捕捉 -->
	    <beans:property name="hideUserNotFoundExceptions" value="false" />
	    
	    <beans:property name="userDetailsService" ref="userDetailService" /> 
	    <!-- <beans:property name="messageSource" ref="messageSource" /> -->
	    <!-- <beans:property name="userCache" ref="userCache" />可使用缓存保存用户信息-->
	    <!-- 开发过程中可以先把这两行注释掉-->
	    <!-- <beans:property name="passwordEncoder" ref="passwordEncode"/>
	    <beans:property name="saltSource" ref="saltSource" />  -->
	</beans:bean>
	<!-- 密码加密 -->
	<beans:bean id="passwordEncode" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />  
	<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">  
		<beans:property name="userPropertyToUse" value="id"/>  
	</beans:bean>
	<beans:bean id="userDetailService" class="com.zheng.service.impl.UserServiceImpl" />
	<!-- 未登录的切入点-->
	<beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<beans:property name="loginFormUrl" value="/service/login/unSecurity" />
	</beans:bean>
	 
</beans:beans>

四、相关代码

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

package com.zheng.shared.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.zheng.bean.User;
import com.zheng.dao.UserMapper;

public class JadeUserPwdAuthFilter extends UsernamePasswordAuthenticationFilter {

	
	public static final String USERNAME = "userName";
	public static final String PASSWORD = "userPassword";
	
	@Autowired
	private UserMapper userDao;
	
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (!request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
		
		String userName = request.getParameter(USERNAME);
		String password = request.getParameter(PASSWORD);

		User user = userDao.findUserByUserName(userName);
		System.out.println("username: " + user.getUsername());
		System.out.println("password: " + user.getPassword());
		
		// 验证用户是否被启用
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(userName, password);
		// 允许子类设置详细属性  
		setDetails(request, authRequest);
		// 运行UserDetailsService的loadUserByUsername 再次封装Authentication 
		return this.getAuthenticationManager().authenticate(authRequest);
	}
}

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

package com.zheng.service;

import org.springframework.security.core.userdetails.UserDetailsService;

public interface UserService extends UserDetailsService{

}

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

package com.zheng.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.zheng.bean.User;
import com.zheng.dao.UserMapper;
import com.zheng.service.UserService;


public class UserServiceImpl implements UserService{

	@Autowired
	private UserMapper userMapper;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User user = null;
		try {
			user = userMapper.findUserByUserName(username);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (user == null) {
			throw new UsernameNotFoundException("用户名或密码不正确!");
		}
		System.out.println("username: " + user.getUsername());
		System.out.println("password: " + user.getPassword());
		
		return user;
	}

}

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

package com.zheng.bean;

import java.io.Serializable;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class User implements UserDetails , Serializable {
	private static final long serialVersionUID = 123L;
	
    private String userName;

    private String password;
	
    private Collection<GrantedAuthority> authorities;// 用户证书是否有效
        
	@Override
	public String getUsername() {
		return this.userName;
	}

	@Override
    public String getPassword() {
        return password;
    }
	
	public void setPassword(String password) {
		this.password = password;
	}
    
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}
	
	public void setAuthorities(Collection<GrantedAuthority> authorities) {
		this.authorities = authorities;
	}
	
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}
	
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

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

 

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

package com.zheng.dao;

import com.zheng.bean.User;

public interface UserMapper {
    /**
     * 根据用户名查找
     * @param userName
     * @return
     */
	User findUserByUserName(String name);
}

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

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zheng.dao.UserMapper" >
  <resultMap id="BaseResultMap" type="com.zheng.bean.User" >
     <result column="name" property="userName" jdbcType="VARCHAR" />
     <result column="password" property="password" jdbcType="VARCHAR" />
  </resultMap>
  
  <select id="findUserByUserName" parameterType="string" resultMap="BaseResultMap" >
    select * from user where name = #{userName}
  </select>

</mapper>

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

	/**
	 * 登陆成功进行处理的方法
	 * @param request
	 * @return
	 */
	@RequestMapping("/loginSucc")
	@ResponseBody
	public Map<String,Object> loginSucc(HttpServletRequest request){
		System.out.println("登录成功!");
		Map<String,Object> result = new HashMap<String,Object>();
		return result;
	}
	
	/**
	 * 登陆失败进行的操作
	 * @param request
	 * @return
	 */
	@RequestMapping("/loginFail")
	@ResponseBody
	public Map<String,Object> loginFail(HttpServletRequest request){
		System.out.println("登录失败!");
		Map<String,Object> result = new HashMap<String,Object>();
		return result;
	}

五、运行结果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值