`
sunjiesh
  • 浏览: 100969 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Spring Security应用实例(一):用户登录

阅读更多

经过Spring Security官方文档及相关资料的学习,自己做了一个简单的用户登录模块,现在将自己写的代码整理处理,以供大家参考或交流,如有不对,请指正错误。

1、库表建立

     1)用户表

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(10) NOT NULL auto_increment,
  `login_name` varchar(20) default NULL,
  `password` varchar(20) default NULL,
  `name` varchar(20) default NULL,
  `email` varchar(30) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     2)角色表

DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     3)权限表

DROP TABLE IF EXISTS `authorities`;
CREATE TABLE `authorities` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(20) default NULL,
  `display_name` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     4)用户-角色表

DROP TABLE IF EXISTS `users_roles`;
CREATE TABLE `users_roles` (
  `user_id` int(10) NOT NULL,
  `role_id` int(10) NOT NULL,
  PRIMARY KEY  (`user_id`,`role_id`),
  KEY `FK_R_2` (`role_id`),
  CONSTRAINT `FK_R_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
  CONSTRAINT `FK_R_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`)

 

    5)角色-权限表

DROP TABLE IF EXISTS `roles_authorities`;
CREATE TABLE `roles_authorities` (
  `role_id` int(10) NOT NULL,
  `authority_id` int(10) NOT NULL,
  PRIMARY KEY  (`role_id`,`authority_id`),
  KEY `FK_R_4` (`authority_id`),
  CONSTRAINT `FK_R_3` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`),
  CONSTRAINT `FK_R_4` FOREIGN KEY (`authority_id`) REFERENCES `authorities` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

2、建立Pojo类

     1)用户

package cn.com.sunjiesh.springmvcdemo.entity;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

/**
 * 统一定义id的entity基类.
 * 
 * @author calvin
 */
@MappedSuperclass
public class IdEntity {

	private Long id;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}
}
 
package cn.com.sunjiesh.springmvcdemo.entity.user;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springside.modules.utils.CollectionUtils;

import cn.com.sunjiesh.springmvcdemo.entity.IdEntity;

/**
 * 用户.
 * 
 * 注意@Cache(Entity与集合的缓存),@ManyToMany/@JoinTable(多对多关系),@OrderBy/LinkedHashSet(集合排序),@Transient(非持久化属性)的应用.
 * 
 * @author calvin
 */
@Entity
@Table(name = "USERS")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User extends IdEntity {

	private String loginName;

	private String password;

	private String name;

	private String email;

	private Set<Role> roles = new LinkedHashSet<Role>();

	@Column(name="login_name")
	public String getLoginName() {
		return loginName;
	}

	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}

	@Column(name="password")
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name="name")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name="email")
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE },fetch=FetchType.EAGER)
	@JoinTable(name = "USERS_ROLES", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
	@OrderBy("id")
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	public Set<Role> getRoles() {
		return roles;
	}

	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	@Transient
	public String getRoleNames() throws Exception {
		return CollectionUtils.fetchPropertyToString(roles, "name", ", ");
	}

	@SuppressWarnings("unchecked")
	@Transient
	public List<Long> getRoleIds() throws Exception {
		return CollectionUtils.fetchPropertyToList(roles, "id");
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}
 

     2)角色

package cn.com.sunjiesh.springmvcdemo.entity.user;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springside.modules.utils.CollectionUtils;

import cn.com.sunjiesh.springmvcdemo.entity.IdEntity;

/**
 * 角色.
 * 
 * 注意@Cache(Entity与集合的缓存),@ManyToMany/@JoinTable(多对多关系),@OrderBy/LinkedHashSet(集合排序),@Transient(非持久化属性)的应用.
 * 
 * @author calvin
 */
@Entity
@Table(name = "ROLES")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Role extends IdEntity {

	private String name;

	private Set<Authority> auths = new LinkedHashSet<Authority>();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE },fetch=FetchType.EAGER)
	@JoinTable(name = "ROLES_AUTHORITIES", joinColumns = { @JoinColumn(name = "ROLE_ID") }, inverseJoinColumns = { @JoinColumn(name = "AUTHORITY_ID") })
	@OrderBy("id")
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	public Set<Authority> getAuths() {
		return auths;
	}

	public void setAuths(Set<Authority> auths) {
		this.auths = auths;
	}

	@Transient
	public String getAuthNames() throws Exception {
		return CollectionUtils.fetchPropertyToString(auths, "displayName", ", ");
	}

	@SuppressWarnings("unchecked")
	@Transient
	public List<Long> getAuthIds() throws Exception {
		return CollectionUtils.fetchPropertyToList(auths, "id");
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}
 

     3)权限

package cn.com.sunjiesh.springmvcdemo.entity.user;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import cn.com.sunjiesh.springmvcdemo.entity.IdEntity;

/**
 * 权限.
 * 
 * @Cache使用READ_ONLY策略.
 * 
 * @author calvin
 */
@Entity
@Table(name = "AUTHORITIES")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Authority extends IdEntity {

	private String name;

	private String displayName;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name="display_name")
	public String getDisplayName() {
		return displayName;
	}

	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}
 

     注意:@ManyToMany中的fetch=FetchType.EAGER。如果fetch=FetchType.LAZY会报异常。

3、建立DAO类

    1)接口

 

package cn.com.sunjiesh.springmvcdemo.dao.iface;

import cn.com.sunjiesh.springmvcdemo.entity.user.User;



/**
 * 
 * @author sunjie
 * @since 2009-03-29
 * 
 */
public interface IUserDAO extends IBaseHibernateDAO<User> {

	public User getUserByUserName(String username);

}
 

    2)实现类

package cn.com.sunjiesh.springmvcdemo.dao.impl;

import org.apache.log4j.Logger;
import org.hibernate.Query;


import cn.com.sunjiesh.springmvcdemo.dao.iface.IUserDAO;
import cn.com.sunjiesh.springmvcdemo.entity.user.User;

public class UserDAOImpl extends BaseHibernateDAOImpl<User> implements IUserDAO {

	private static Logger LOG = Logger.getLogger(UserDAOImpl.class);

	public User getUserByUserName(String username) {
		String hql = "from User where loginName = ?";
		Query query = getSession().createQuery(hql);
		query.setParameter(0, username);
		User user = (User) query.list().get(0);
		return user;
	}

}

 

4、Spring Security相关代码

package cn.com.sunjiesh.springmvcdemo.service.security;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;

import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;

import cn.com.sunjiesh.springmvcdemo.dao.iface.IUserDAO;
import cn.com.sunjiesh.springmvcdemo.entity.user.Authority;
import cn.com.sunjiesh.springmvcdemo.entity.user.Role;
import cn.com.sunjiesh.springmvcdemo.entity.user.User;



/**
 * 实现SpringSecurity的UserDetailsService接口,获取用户Detail信息.
 * @author calvin
 */
public class UserDetailServiceImpl implements UserDetailsService{

	private static Logger LOG=Logger.getLogger(UserDetailServiceImpl.class);
	
	private IUserDAO userDao;
	
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		if(username==null){
			LOG.error("username is null");
		}
		if(userDao==null){
			LOG.error("userDao is null");
		}
		User user=userDao.getUserByUserName(username);
		//TOTO 判断用户存在,如果不存在,则抛出异常。
		if(user==null){
			LOG.error(username+" is not exist", new UsernameNotFoundException(username+" is not exist"));
		}
		
		List<GrantedAuthority> authsList = new ArrayList<GrantedAuthority>();
		
		System.out.println("user.getRoles().size()="+user.getRoles().size());
		for (Role role : user.getRoles()) {
			for (Authority authority : role.getAuths()) {
				authsList.add(new GrantedAuthorityImpl(authority.getName()));
			}
		}
		
		//TODO 
		org.springframework.security.userdetails.User userdetail = new org.springframework.security.userdetails.User(
				user.getLoginName(), user.getPassword(), true, true, true, true, authsList
						.toArray(new GrantedAuthority[authsList.size()]));

		return userdetail;
	}

	public void setUserDao(IUserDAO userDao) {
		this.userDao = userDao;
	}
}
 

5、配置文件

    1)web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name> SpringMVCDemo</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/cn/com/sunjiesh/springmvcdemo/spring/spring-*.xml,/WEB-INF/springmvcdemo-servlet.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!--
		Spring Security可以限制一个主体并行认证到同一系统的次数。
		很多ISV利用这点来加强授权公里,网管也喜欢这个功能,因为它可以防止人们共享登录名。
		你可以,比如,禁止用户"Batman"从两个不同的会话登录到web应用里。
	-->
	<listener>
		<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
	</listener>
	
	
   	<!--Character Encoding Convert-->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class> org.springframework.web.filter.CharacterEncodingFilter 
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>gb2312</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>*.do</url-pattern>
	</filter-mapping>
	<!-- Spring Security Filter-->
	<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>
	
	<!-- Use DWR -->
	<servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>dwr-invoker</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>
    <!-- Spring MVC Dispatcher -->
	<servlet>
		<servlet-name>springmvcdemo</servlet-name>
		<servlet-class> org.springframework.web.servlet.DispatcherServlet 
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>WEB-INF/springmvcdemo-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvcdemo</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	
	<!-- JSTL Configuration -->
	<jsp-config>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
			<taglib-location>/WEB-INF/tlds/fmt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/fmt-rt</taglib-uri>
			<taglib-location>/WEB-INF/tlds/fmt-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
			<taglib-location>/WEB-INF/tlds/c.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/core-rt</taglib-uri>
			<taglib-location>/WEB-INF/tlds/c-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
			<taglib-location>/WEB-INF/tlds/sql.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/sql-rt</taglib-uri>
			<taglib-location>/WEB-INF/tlds/sql-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
			<taglib-location>/WEB-INF/tlds/x.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/x-rt</taglib-uri>
			<taglib-location>/WEB-INF/tlds/x-rt.tld</taglib-location>
		</taglib>
	</jsp-config>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>
 

 

    2)spring-base.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:/cn/com/sunjiesh/springmvcdemo/spring/jdbc.properties</value>
			</list>
		</property>
	</bean>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<!-- Hibernate Annotation Entity -->
		<property name="annotatedClasses">
			<list>
				<value>cn.com.sunjiesh.springmvcdemo.entity.user.Authority</value>
				<value>cn.com.sunjiesh.springmvcdemo.entity.user.Role</value>
				<value>cn.com.sunjiesh.springmvcdemo.entity.user.User</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
				<prop key="hibernate.cache.use_second_level_cache">false</prop>
				<prop key="hibernate.cache.use_query_cache">false</prop>
			</props>
		</property>
	</bean>
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
	<bean id="baseTxService"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
		abstract="true">
		<property name="transactionManager" ref="txManager" />
		<property name="proxyTargetClass" value="true" />
		<property name="transactionAttributes">
			<props>
				<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="update*">PROPAGATION_REQUIRED</prop>
				<prop key="remove*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>
</beans>
 

    3)spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!-- 
	Author By Sun Jie
	Shared document
-->
<beans default-autowire="byName" default-lazy-init="true">
	
	<!-- Add By Sun Jie -->
	<bean id="userDaoTarget" class="cn.com.sunjiesh.springmvcdemo.dao.impl.UserDAOImpl">
	</bean>
	<!-- End Edit -->
	
	<!-- Add By Sun Jie -->
	<bean id="userDao" parent="baseTxService">
		<property name="target">
			<ref bean="userDaoTarget"/>
		</property>
	</bean>
	<!-- End Edit -->
</beans>
 

    4)spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
	<!--
		FilterChainProxy会按顺序来调用这些filter,使这些filter能享用Spring Ioc的功能
	-->
	<bean id="springSecurityFilterChain" class="org.springframework.security.util.FilterChainProxy">
		<security:filter-chain-map path-type="ant">
			<security:filter-chain pattern="/user/**"
				filters="httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter" />
		</security:filter-chain-map>
	</bean>
	<!--
		集成过滤器(HttpSessionContextIntegrationFilter是集成过滤器的一个实现)
		每次request前HttpSessionContextIntegrationFilter从Session中获取Authentication对象,在request完后
		又把Authentication对象保存到Session中供下次request使用,此filter必须在其他Acegi filter前使用
	-->
	<bean id="httpSessionContextIntegrationFilter"
		class="org.springframework.security.context.HttpSessionContextIntegrationFilter" />
    
    <!--
        退出(Logout)过滤器 退出登录操作
    -->
	<bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
        <!-- 退出系统后系统跳转到此URL -->
		<constructor-arg value="/login.action" />
        <!-- 退出系统后的操作(调用logout方法) -->
		<constructor-arg>
			<list>
                <!-- 实现了LogoutHandler接口(logout方法) -->
				<ref bean="rememberMeServices" />
				<bean
					class="org.springframework.security.ui.logout.SecurityContextLogoutHandler" />
			</list>
		</constructor-arg>
	</bean>
	<!--
		处理表单认证filter: 1.authenticationManager 认证管理器 2.authenticationFailureUrl
		定义登录失败时转向的页面 3.defaultTargetUrl 定义登录成功时转向的页面 4.filterProcessesUrl
		定义登录请求的地址 5.rememberMeServices 在验证成功后添加cookie信息
	-->
	<bean id="authenticationProcessingFilter"
		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
		<property name="authenticationManager" ref="authenticationManager"></property>
		<property name="authenticationFailureUrl" value="/user/login.jsp"></property>
		<property name="defaultTargetUrl" value="/user/index.jsp"></property>
		<property name="filterProcessesUrl" value="/user/j_spring_security_check"></property>
		<property name="rememberMeServices" ref="rememberMeServices"></property>
	</bean>
	
	<!-- 基本认证机制处理 -->
	<bean id="basicProcessingFilter"
		class="org.springframework.security.ui.basicauth.BasicProcessingFilter">
		<property name="authenticationManager">
			<ref bean="authenticationManager" />
		</property>
		<property name="authenticationEntryPoint">
			<bean id="authenticationEntryPoint"
				class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint">
				<property name="realmName">
					<value>Name Of Your Realm</value>
				</property>
			</bean>
		</property>
	</bean>
	<bean id="securityContextHolderAwareRequestFilter"
		class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter" />
		<!--
        如果不存在任何授权信息时,自动添加匿名用户身份至SecurityContextHolder中
    -->
	<bean id="anonymousProcessingFilter"
		class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter">
		<property name="key" value="springsecurity"></property>
		<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"></property>
	</bean>
	<!--
		异常处理filter(异常转换过滤器),主要是处理AccessDeniedException和AuthenticationException,
		将给每个异常找到合适的"去向"
	-->
	<bean id="exceptionTranslationFilter"
		class="org.springframework.security.ui.ExceptionTranslationFilter">
		<property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint" />
		<property name="accessDeniedHandler">
			<bean class="org.springframework.security.ui.AccessDeniedHandlerImpl">
				<property name="errorPage" value="/accessDenied.jsp" />
			</bean>
		</property>
	</bean>
	<!--
		使用过滤器安全拦截器保护资源
		filterSecurityInterceptor在执行转向目标url前检查objectDefinitionSource中设定的用户权限信息,
		安全强制过滤器负责拦截请求,判断请求是否安全,并且给予认证和访问决策管理器一个机会来验证用户的身份和权限 过程:
		首先,过滤器安全拦截器使用authenticationManager调用自己的provider来对用户的认证信息进行验证并获取用户已有的权限。
		然后,使用访问决策管理器来判断用户是否拥用合适的授权来访问受保护的资源。
		(objectDefinitionSource属性定义了访问URL需要的权限信息)
		最后,有投票者根据用户持有认证和访问url需要的属性,调用自己的voter来投票,决定是否允许访问。
	-->
	<bean id="filterSecurityInterceptor"
		class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
		<property name="authenticationManager" ref="authenticationManager"></property>
		<property name="accessDecisionManager" ref="accessDecisionManager"></property>
		<!--
			<property name="objectDefinitionSource"
			ref="objectDefinitionSource"></property>
		-->
		<property name="objectDefinitionSource">
			<security:filter-invocation-definition-source>
				<security:intercept-url pattern="/secure/super/**"
					access="ROLE_WE_DONT_HAVE" />
				<security:intercept-url pattern="/secure/**"
					access="ROLE_SUPERVISOR,ROLE_TELLER" />
				<security:intercept-url pattern="/login.action*"
					access="IS_AUTHENTICATED_ANONYMOUSLY" />
				<security:intercept-url pattern="/user/user!save.action*"
					access="ROLE_MODIFY_USER" />
				<security:intercept-url pattern="/user/user!delete.action*"
					access="ROLE_MODIFY_USER" />
				<security:intercept-url pattern="/user/user*.action*"
					access="ROLE_VIEW_USER" />
				<security:intercept-url pattern="/user/role!save.action*"
					access="ROLE_MODIFY_ROLE" />
				<security:intercept-url pattern="/user/role!delete.action*"
					access="ROLE_MODIFY_ROLE" />
				<security:intercept-url pattern="/user/role*.action*"
					access="ROLE_VIEW_ROLE" />
			</security:filter-invocation-definition-source>
		</property>
	</bean>
	<!--
		访问决策管理器
		验证用户是否有权限访问相应的资源(filterSecurityInterceptor中objectDefinitionSource属性定义的访问URL需要的属性信息)
	-->
	<bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased"
		p:allowIfAllAbstainDecisions="false">
		<property name="decisionVoters">
			<list>
				<bean class="org.springframework.security.vote.RoleVoter" />
				<bean class="org.springframework.security.vote.AuthenticatedVoter" />
			</list>
		</property>
	</bean>
	<bean id="authenticationProcessingFilterEntryPoint"
		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
		<property name="loginFormUrl" value="/login.jsp" />
		<property name="forceHttps" value="false" />
	</bean>
	<!--
		认证管理器(org.springframework.security.AuthenticationManager接口)
		org.springframework.security.providers.ProviderManager是认证管理器的一个实现,
		ProviderManager通过遍历一个提供者的集合来实现身份验证, 直到某一个认证提供者能够成功地验证该用户的身份
	-->
	<!--
		通过Providers提供认证者列表,如果一个认证提供者失败可以尝试另外一个认证提供者,以保证获取不同来源的身份认证,如
		DaoAuthenticationProvider 从数据库中读取用户信息验证身份
		AnonymousAuthenticationProvider 匿名用户身份认证
		RememberMeAuthenticationProvider 已存cookie中的用户信息身份认证 其它的还有
		AuthByAdapterProvider 使用容器的适配器验证身份 CasAuthenticationProvider
		根据Yale中心认证服务验证身份, 用于实现单点登陆 JaasAuthenticationProvider
		从JASS登陆配置中获取用户信息验证身份 RemoteAuthenticationProvider 根据远程服务验证用户身份
		RunAsImplAuthenticationProvider 对身份已被管理器替换的用户进行验证
		X509AuthenticationProvider 从X509认证中获取用户信息验证身份
		TestingAuthenticationProvider 单元测试时使用
		每个认证者会对自己指定的证明信息进行认证,如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationToken这个证明信息进行认证。
	-->
	<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
		<property name="providers">
			<list>
				<ref local="daoAuthenticationProvider" />
				<ref local="anonymousAuthenticationProvider" />
			</list>
		</property>
		<!-- <property name="sessionController" ref="concurrentSessionController" /> -->
	</bean>
	<bean id="daoAuthenticationProvider"
		class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
		<!--  <property name="passwordEncoder" ref="passwordEncoder"></property>-->
		<property name="userDetailsService" ref="userDetailsService"></property>
	</bean>
	<bean id="anonymousAuthenticationProvider"
		class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider">
		<property name="key" value="springsecurity"></property>
	</bean>
	<!-- RemeberMeServices -->
	<bean id="rememberMeServices"
		class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
		<property name="key" value="springsecurity"></property>
		<property name="userDetailsService" ref="userDetailsService"></property>
	</bean>
	<bean id="userDetailsService"
		class="cn.com.sunjiesh.springmvcdemo.service.security.UserDetailServiceImpl">
		<property name="userDao" ref="userDao"></property>
		</bean>
	<bean id="passwordEncoder"
		class="org.springframework.security.providers.encoding.Md5PasswordEncoder" />
	<bean id="loggerListener"
		class="org.springframework.security.event.authentication.LoggerListener" />
</beans>
 

    5)springmvcdemo-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	Author Sun Jie
 -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

	<!-- Multi-Action-->
	<bean id="methodNameResolver"
		class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
		<property name="paramName" value="method" />
		<property name="defaultMethodName" value="index" />
	</bean>
	<!-- View Resolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass"
			value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/" />
	</bean>
	<bean id="adminHandlerMapping"
		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<!-- Add By Sun Jie -->
				<prop key="/user/login.do">userLoginController</prop>
				<!-- Add By Sun Jie -->
			</props>
		</property>
	</bean>
	
	<bean id="userLoginController" class="cn.com.sunjiesh.springmvcdemo.web.user.LoginController"
		autowire="byName">
		<property name="successView" value="/user/index.jsp" />
		<property name="errorView" value="" />
	</bean>
</beans>
 

6、页面

<%@ page contentType="text/html;charset=gb2312"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<%@ page import="org.springframework.security.ui.AbstractProcessingFilter"%>
<%@ page import="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"%>
<%@ page import="org.springframework.security.AuthenticationException"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>SpringMVCDemo登录页</title>
		<%@ include file="/common/meta.jsp"%>
		<script src="${ctx}/js/validate/jquery.validate.js" type="text/javascript"></script>
		<script src="${ctx}/js/validate/messages_cn.js" type="text/javascript"></script>
  		<script>
  			$(document).ready(function(){
    			$("#loginForm").validate();
 			 });
  		</script>
	</head>
	<body>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
		<div id="content">
			<%
				if (session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY) != null) {
			%>
			<span style="color:red"> 登录失败,请重试. </span>
			<%
				}
			%>
			<h2>SpringMVCDemo示例</h2>
			<h3>--CRUD管理界面演示</h3>
			<form id="loginForm" action="${ctx}/user/j_spring_security_check" method="post">
				<table class="inputView">
					<tr>
						<td>
							用户名:
						</td>
						<td>
							<input type='text' name='j_username'
								<c:if test="${not empty param.error}"> value='<%=session.getAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY)%>'</c:if> class="required"/>
						</td>
					</tr>
					<tr>
						<td>
							密码:
						</td>
						<td>
							<input type='password' name='j_password' class="required" />
						</td>
					</tr>
					<tr>
						<td colspan='2'>
							<input value="登录" type="submit" />
						</td>
					</tr>
				</table>
			</form>
		</div>
	</body>
</html>

 备注:登录页面上的表单action与spring-security中authenticationProcessingFilter过滤器中的filterProcessesUrl相对应。用户名与输入框的name属性值分别是j_username与j_password。

 

18
2
分享到:
评论
10 楼 heathcliffchen 2011-11-27  
能否给我一套源码,谢谢!heathcliffchen@yeah.net
9 楼 joypaker 2011-11-22  
楼主能给提供一下源码吗,谢谢 qiujie445300@163.com
8 楼 gyl868 2010-03-16  
楼主能给提供一下源码吗,谢谢 gyl8680@gmail.com
7 楼 cpliu903 2010-02-28  
请问可以提供war 测试吗
6 楼 sunjiesh 2010-02-26  
我可不是calvin,说到底也是借鉴各位大大的文章,哈哈。
5 楼 longxiaoyan 2010-02-23  
难道楼主就是calvin?springside值得研究。
4 楼 liujianst 2009-05-17  
lz交个朋友

qq:273311453
3 楼 halk 2009-05-05  
盼具体代码..
2 楼 sunshan 2009-04-17  
现在spring security 使用命名空间方法极大简化了xml配置,楼主可以尝试一下
1 楼 idealab 2009-04-12  
很强大~

相关推荐

    spring security 完整项目实例

    Spring Security 是一个强大的安全框架,用于为Java应用提供身份验证和授权服务。在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、...

    一个比较好的spring security实例

    Spring Security 是一个强大的安全框架,主要用于Java应用的安全管理。它提供了认证、授权和访问控制等功能,使得开发者可以轻松地在应用程序中实现复杂的安全需求。在这个名为 "mysecurity" 的压缩包中,很可能是...

    Spring Security 完整实例

    这个Spring Security实例展示了如何深度定制框架以适应实际项目的需求。从数据库集成到用户界面,每个环节都体现了Spring Security的灵活性和可扩展性。通过理解并实践这些示例,开发者能够更好地理解和掌握Spring ...

    maven+springMVC+spring security权限实例

    【标题】"maven+springMVC+spring security权限实例"是一个综合性的IT项目,它展示了如何使用Maven构建一个基于Spring MVC和Spring Security的权限管理应用。这个实例旨在帮助开发者快速理解并实践这三大技术在实际...

    springsecurity入门实例

    本教程将引导你逐步了解如何使用 Spring Security 构建一个入门实例。 **一、Spring Security 基础概念** 1. **访问控制**:Spring Security 提供了基于角色的访问控制(RBAC),允许开发者定义哪些用户或角色可以...

    spring security acl 实例

    spring security acl 代码实例 spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例spring security acl 代码实例

    Spring Security3.1实例

    Spring Security 是一个强大的安全框架,用于Java应用的安全管理。它提供了认证、授权和访问控制功能,使得开发者可以轻松地在应用程序中实现复杂的安全需求。在3.1版本中,Spring Security 进一步优化了其核心架构...

    Spring Security应用实例

    在本篇"Spring Security应用实例"中,我们将探讨如何利用Spring Security框架构建一个基础的用户登录模块。Spring Security是Spring生态系统中的一个强大安全组件,它提供了全面的安全管理框架,包括认证、授权、...

    spring security3配置和使用实例+教程

    教程文档`教你使用_SpringSecurity_3.0_52页.pdf`会详细指导你如何一步步配置和使用Spring Security。它应该包含了配置文件的示例、如何集成到Spring应用中、如何创建自定义认证逻辑以及如何进行授权设置等内容。...

    基本的spring mvc + spring security实现的登录(无数据库)

    在本项目中,我们主要探讨的是如何利用Spring MVC和Spring Security框架构建一个基本的无数据库登录系统。Spring MVC是Spring框架的一部分,用于处理Web应用程序的请求-响应模型,而Spring Security则是一个强大的...

    springSecurity简易实例

    以上就是一个基础的Spring Security实例,它实现了基本的访问控制和表单登录功能。在实际项目中,你可能需要根据需求进行更复杂的配置,例如自定义登录逻辑、权限管理、记住我功能、CSRF保护等。Spring Security提供...

    SpringBoot + SpringSecurity + JPA 实现用户角色权限登录认证

    在这个项目中,SpringSecurity被用来处理用户登录、角色权限分配和防止非法请求。 3. **JPA**:Java Persistence API是Java平台上的ORM(对象关系映射)规范,它允许开发者以面向对象的方式操作数据库,将数据对象...

    SpringSecurity入门Demo实例

    在这个入门Demo实例中,我们将探讨如何配置和使用Spring Security来保护我们的Java应用。教程链接提及的CSDN博客文章提供了详细的步骤,指导我们逐步创建一个基本的Spring Security应用。 首先,我们需要在项目中...

    Spring Security 安全实例-数据库简单应用(用户从数据库中获取)

    通过Spring Security,我们可以方便地实现用户登录、权限控制、会话管理等功能,同时支持多种认证机制,包括基于数据库的用户信息存储。 ### 2. 数据库用户存储配置 在传统的Spring Security配置中,用户信息通常...

    spring security配置实例

    #### 一、Spring Security简介与应用场景 Spring Security 是一个功能强大的安全框架,提供了全面的安全服务,支持认证、授权以及其他安全服务。它为开发人员提供了高度可定制化的安全解决方案,适用于各种复杂的...

    Spring Security 配置实例XML文件

    Spring Security 配置实例XML文件

    springSecurity3实例

    标题中的“springSecurity3实例”意味着我们将探讨如何实际操作Spring Security 3,通过具体的项目来理解其工作原理和配置。这通常涉及到创建安全过滤器链,配置不同的安全拦截规则,以及设置用户权限。 描述中的...

    Spring security 应用实例帮助文件资源

    spring security 应用 实例, 包含自己写的项目例子。。。Spring security 应用实例帮助文件资源。。

    spring整合security4.2完整实例

    在Spring 4.3.18版本中,它与Spring Security 4.2.7进行了集成,构建了一个完整的项目实例,旨在帮助开发者理解如何在实际开发环境中配置和使用Spring Security。 在Spring Security 4.2中,主要包含以下几个核心...

Global site tag (gtag.js) - Google Analytics