使用spring-security3.1 + spring mvc + Hibernate 控制系统权限


第一步

下载spring-security3.1

解压后进入dist目录,里面有两个war文件,解压其中一个。

然后将里面的jar包全部复制到项目中。

官方中文文档下载地址:http://www.asdtiang.org/wp-content/uploads/2011/09/Spring-Security-3.0.1-%E4%B8%AD%E6%96%87%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3.pdf

 

第二步

配置web.xml spring的监听器, 以及spring-mvc的监听器

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<display-name></display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>  
        classpath*:applicationContext.xml,
        </param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>  
          <param-name>contextConfigLocation</param-name>  
          <param-value>classpath*:spring-mvc.xml</param-value>  
        </init-param>  
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	
	
</web-app>

加入applicationContext.xml与spring-mvc.xml到src目录

applicationContext.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
            http://www.springframework.org/schema/context  
            http://www.springframework.org/schema/context/spring-context-3.0.xsd  
            http://www.springframework.org/schema/mvc   
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
	<!-- 启用注解方式 -->
	<context:annotation-config />
	
	<context:component-scan base-package="com.zf" />
	
	<!-- 启用mvc注解 -->
	<mvc:annotation-driven />
	
</beans>  

spring-mvc.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<!-- 视图解析器 -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
		

</beans>  


第三步

加入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:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
			http://www.springframework.org/schema/security 
			http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	
	<!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面  -->
	<security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" >
	
	</security:http>
	
	<!-- 配置一个认证管理器 -->
	<security:authentication-manager>
		<security:authentication-provider>
			<security:user-service>
				<!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
				<security:user name="admin" password="admin" authorities="ROLE_USER"/>
			</security:user-service>
		</security:authentication-provider>
	</security:authentication-manager>
	
</beans>



第四步

在web.xml中配置SpringSecurity拦截器(如果不先进行第三步的配置,下面配置完之后,tomcat启动会报错)

<!-- 配置SpringSecurity -->
	<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>
	


好了,现在已经配置完成,tomcat已经可以启动了。但是还没有配置具体的权限策略。


第五步

配置Hibernate

在applicationContext.xml中配置JPA

	<!-- 开启注解事物 -->
	 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />  
	
	<!-- 配置hibernate -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">     
       <!-- 指定连接数据库的驱动 -->     
       <property name="driverClass" value="com.mysql.jdbc.Driver"/>     
       <!-- 指定连接数据库的URL -->     
       <property name="jdbcUrl" value="jdbc:mysql:///spring-scurity"/>     
       <!-- 指定连接数据库的用户名 -->     
       <property name="user" value="root"/>     
       <!-- 指定连接数据库的密码 -->     
       <property name="password" value="root"/>     
       <!-- 指定连接数据库连接池的最大连接数 -->     
       <property name="maxPoolSize" value="20"/>     
       <!-- 指定连接数据库连接池的最小连接数 -->     
       <property name="minPoolSize" value="1"/>     
       <!-- 指定连接数据库连接池的初始化连接数 -->     
       <property name="initialPoolSize" value="1"/>     
       <!-- 指定连接数据库连接池的连接的最大空闲时间 -->     
       <property name="maxIdleTime" value="20"/>     
    </bean>   
      
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >  
            <property name="dataSource" ref="dataSource"></property>  
            <property name="hibernateProperties">  
                <props>  
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
                    <prop key="hibernate.show_sql">true</prop>  
                    <prop key="hibernate.query.substitutions">true 1,false 0</prop>  
                    <prop key="hibernate.hbm2ddl.auto">update</prop>  
                </props>  
            </property>  
            <property name="packagesToScan">  
                <list>  
                    <value>com.zf.pojo</value>   
                </list>  
            </property>       
    </bean>  
      
    <!-- 事务管理器 -->  
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
        <property name="sessionFactory" ref="sessionFactory"></property>  
    </bean>  
  

第六步

编写实体类与DAO

package com.zf.pojo;

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

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "etuser")
public class ETUser {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id ;
	
	private String username ;
	
	private String password ;
	
	private int age ;
	
	@ManyToMany
	@JoinTable(name="user_role" , joinColumns = {
			@JoinColumn(name = "userid")
	}, inverseJoinColumns = {@JoinColumn(name="roleid")}) 
	private List<ETRole> roles = new ArrayList<ETRole>();  
	
	@Temporal(TemporalType.DATE)
	private Date regDate ;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Date getRegDate() {
		return regDate;
	}

	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}

	public List<ETRole> getRoles() {
		return roles;
	}

	public void setRoles(List<ETRole> roles) {
		this.roles = roles;
	}
	
	
}


package com.zf.pojo;

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

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "etrole")
public class ETRole {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	
	private String roleCode ;
	
	private String despripe ;
	
	
	@ManyToMany
	@JoinTable(name="user_role" , joinColumns = {
			@JoinColumn(name = "roleid")
	}, inverseJoinColumns = {@JoinColumn(name="userid")}) 
	private List<ETUser> users = new ArrayList<ETUser>();

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getRoleCode() {
		return roleCode;
	}

	public void setRoleCode(String roleCode) {
		this.roleCode = roleCode;
	}

	public String getDespripe() {
		return despripe;
	}

	public void setDespripe(String despripe) {
		this.despripe = despripe;
	}

	public List<ETUser> getUsers() {
		return users;
	}

	public void setUsers(List<ETUser> users) {
		this.users = users;
	}

	
}


package com.zf.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.zf.pojo.ETUser;

@Service("UserDao")
@Transactional(propagation = Propagation.REQUIRED)
public class UserDao extends HibernateDaoSupport{
	
	
	/**
	 * 根据用户名查询用户
	 * @param username
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ETUser findUserByUserName(String username){
		List<ETUser> result =  getHibernateTemplate().find("from ETUser e where e.username = ?"
				, username );
		if(result != null && !result.isEmpty())    
			return result.get(0);
		return null ;
	}

	/**
	 * 根据用户名和密码查询用户
	 * @param username
	 * @param password
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ETUser findUserBuNameAndPwd(String username , String password){
		List<ETUser> result =  getHibernateTemplate().find("from ETUser e where e.username = ? and e.password = ?"
				, username , password);
		if(result != null && !result.isEmpty())  
			return result.get(0);
		return null ;
	}
	
	@Resource(name = "sessionFactory")
	public void setMySessionFactory(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}


}



 
 

下面来配置使用数据库中的用户。.

编写处理用户信息的UserDetailsService实现类

package com.zf.service;

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

import javax.annotation.Resource;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
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;
import org.springframework.stereotype.Repository;

import com.zf.dao.UserDao;
import com.zf.pojo.ETRole;
import com.zf.pojo.ETUser;

/**
 * 该类用户从数据库获取用户信息和用户权限信息 提供给spring-security使用
 * @author Administrator
 *
 */
@Repository("ETUserDetailService")
public class ETUserDetailService implements UserDetailsService{

	@Resource(name = "UserDao")
	private UserDao userdao ;
	
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		ETUser etuser = userdao.findUserByUserName(username);
		UserDetails user = null ;
		if(etuser != null){
			user = new User(username, etuser.getPassword(), true,
					true , 
					true,
					true,findUserAuthorities(etuser) );
		}
		
		return user;
	}

	/**
	 * 获取用户的权限
	 * @param user
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public Collection<GrantedAuthority> findUserAuthorities(ETUser user){
		List<GrantedAuthority> autthorities = new ArrayList<GrantedAuthority>();
		List<ETRole> roles =  user.getRoles();
		System.out.println(roles.size());
		for (ETRole etRole : roles) {
			autthorities.add(new GrantedAuthorityImpl(etRole.getRoleCode()));
		}
		return autthorities ;
	}
	
	
}


配置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:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
			http://www.springframework.org/schema/security 
			http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	
	<!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面  -->
	<security:http auto-config="true" use-expressions="true" access-denied-page="/powermiss.jsp" >
		
		<!-- 对登录页面,所有的用户都可以访问 -->		
		<security:intercept-url pattern="/login.jsp"  access="permitAll" />
		<!-- 对所有的资源,都必须要有ROLE_USER角色的用户 才可以访问 -->
		<security:intercept-url pattern="/*"  access="hasRole('ADMIN')" />
		<!-- 配置登录页面为login.jsp ,登录成功默认跳转到index.jsp,登录失败返回login.jsp并携带参数error=true -->
		<security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" />
		
	</security:http>
	
	<!-- 配置一个认证管理器 -->
	<security:authentication-manager>
		<!-- 使用自定义的UserDetailService  -->
		<security:authentication-provider user-service-ref="ETUserDetailService">
		<!-- 下面的内容就可注释掉了 -->
<!-- 			<security:user-service> -->
				<!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
<!-- 				<security:user name="admin" password="admin" authorities="ROLE_USER"/> -->
<!-- 			</security:user-service> -->
		</security:authentication-provider>
	</security:authentication-manager>
	
</beans>

web.mvc 中配置openSessionInView

<filter>
		<filter-name>openSessionInView</filter-name>
		<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
		<init-param>
			<param-name>singleSession</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	
	<filter-mapping>
		<filter-name>openSessionInView</filter-name>
		<url-pattern>*.action</url-pattern>
	</filter-mapping>
	
	<!-- 如果配置opensessionInView ,别忘了给login的action也加上 -->
	<filter-mapping>
		<filter-name>openSessionInView</filter-name>
		<url-pattern>/j_spring_security_check</url-pattern>
	</filter-mapping>
	
	


spring-mvc.xml 中配置OpenSessionInView 

<!-- 处理在类级别上的@RequestMapping注解 -->
	<bean
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
		<property name="interceptors">        <!-- 配置过滤器 -->
			<list>
				<ref bean="openSessionInView" />
			</list>
		</property>
	</bean>


	<!-- 将OpenSessionInView 打开 -->
	<bean id="openSessionInView"
		class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>


编写测试用的页面。

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  <body>
    <h3>用户登录</h3>
    <!-- from的action地址,以及用户名密码的name 。都是spring-security固定的。 -->
   	 <form action="<%=basePath %>j_spring_security_check" method="post">    
  
        <p>  
            <label for="j_username">Username</label> <input id="j_username"  
                name="j_username" type="text" />  
        </p>  
  
        <p>  
            <label for="j_password">Password</label> <input id="j_password"  
                name="j_password" type="password" />  
        </p>  
  		
        <input type="submit" value="Login" />  
  
    </form>  
    
  </body>
</html>

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
       
  <body>       
  		<h3>登录成功,欢迎您:<sec:authentication property="name" /></h3>      
  		<a href="<%=basePath%>admin.jsp">进入管理员页面</a>
  		<a href="<%=basePath%>vip.jsp">进入会员页面</a>
  		<a href="<%=basePath%>auth/logout">注销</a>  
  </body>
</html>

admin.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <body>  
  		<h3>管理员页面</h3>
  </body>
</html>


<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <body>  
  		<h3>会员页面</h3>    
  </body>
</html>


powermiss.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'powermiss.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->


  </head>
  
  <body>
  	
  	<h1 style="color: red;">对不起,您无权访问该资源!</h1>
  	
  </body>
</html>

重新配置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:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
			http://www.springframework.org/schema/security 
			http://www.springframework.org/schema/security/spring-security-3.1.xsd">
	
	<!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面  -->
	<security:http auto-config="true" use-expressions="true" access-denied-page="/powermiss.jsp" >
		
		<!-- 对登录页面,所有的用户都可以访问 -->		
		<security:intercept-url pattern="/login.jsp*"  access="permitAll" />
		<security:intercept-url pattern="/vip.jsp*"  access="hasRole('VIP')" />
		<security:intercept-url pattern="/admin.jsp*"  access="hasRole('ADMIN')" />
		<!-- 对所有的资源,都必须要有COMM权限 才可以访问 -->
		<security:intercept-url pattern="/*"  access="hasRole('COMM')" />
		<!-- 配置登录页面为login.jsp ,登录成功默认跳转到index.jsp,登录失败返回login.jsp并携带参数error=true -->
		<security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" />
		<!-- 退出配置 -->
		<security:logout invalidate-session="true" logout-success-url="/login.jsp" logout-url="/auth/logout"/>
	
	</security:http>
	
	<!-- 配置一个认证管理器 -->
	<security:authentication-manager>
		<!-- 使用自定义的UserDetailService  -->
		<security:authentication-provider user-service-ref="ETUserDetailService">
		<!-- 下面的内容就可注释掉了 -->
<!-- 			<security:user-service> -->
				<!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
<!-- 				<security:user name="admin" password="admin" authorities="ROLE_USER"/> -->
<!-- 			</security:user-service> -->
		</security:authentication-provider>
	</security:authentication-manager>
	
</beans>

向数据库中添加测试数据。

使用spring-security3.1 + spring mvc + Hibernate 控制系统权限_第1张图片


然后就可以测试访问了。



使用注解方式对指定的方法进行权限控制

AdminService.java

package com.zf.service;

import javax.annotation.security.RolesAllowed;

import org.springframework.security.access.prepost.PreAuthorize;

public interface AdminService {

	/* 拥有 Admin 权限才能的方法 ,必须定义在接口上面*/  
	@PreAuthorize("hasRole('ADMIN')")
	public String test01() ;    
	
	@RolesAllowed({"ADMIN"})
	public String test02();
	
	/* 上面的两种注解都可以 */
	
}


AdminServiceImpl.java
package com.zf.service;

import org.springframework.stereotype.Service;

@Service("AdminServiceImpl")
public class AdminServiceImpl implements AdminService{
	   
	public String test01(){    
		System.out.println("方法test01被Admin用户调用");
		return "success";
	}

	public String test02() {
		System.out.println("方法test02被Admin用户调用");
		return "success";
	}

}

package com.zf.control;

import javax.annotation.Resource;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.zf.service.AdminService;

@Controller
@RequestMapping("/admin/")
@Scope("request")
public class AdminController {
    
	@Resource(name = "AdminServiceImpl")
	private AdminService adminService;
	
	@RequestMapping(value = "test01")
	public ModelAndView test01(){
		ModelAndView mav = new ModelAndView("admin");  
		System.out.println(adminService.test01());
		return mav ;
	}
	
	
	@RequestMapping(value = "test02")
	public ModelAndView test02(){
		ModelAndView mav = new ModelAndView("admin");  
		System.out.println(adminService.test01());
		return mav ;
	}
	
	
}

向index.jsp中添加两个链接

<a href="<%=basePath%>admin/test01.action">/admin/test01</a>
  <a href="<%=basePath%>admin/test02.action">/admin/test02</a>


现在就可以测试了。



在jsp页面使用security标签需要引入<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>库


如果是使用freemarker ,配置方法见 http://blog.sina.com.cn/s/blog_55bba7c10100h5bz.html



其他功能

在http标签内配置

<!-- 配置session失效之后跳转到的页面 session-authentication-error-url指向的是登录被限制后跳转到的页面 -->
		<security:session-management invalid-session-url="/sessiontimeout.jsp"  session-authentication-error-url="/loginerror.jsp">
			<!-- 配置一个帐号同时只能有一个会话,这样当有第二个用户登录的时候,第一个用户就会失效 -->
			<security:concurrency-control max-sessions="1" />
			<!-- 配置一个帐号同时智能有一个会话 ,并且第第二个尝试登录的账户不能让他登录,然后跳转到session-authentication-error-url指向的页面-->
			<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"   />
		</security:session-management>


配置登录验证码实例:

写一个VolidateAuthCodeUsernamePasswordAuthenticationFilter继承UsernamePasswordAuthenticationFilter用于验证用户登录

package com.zf.myfilter;

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

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * 扩展UsernamePasswordAuthenticationFilter加上验证码的功能
 *   
 * @author Administrator
 *
 */
public class VolidateAuthCodeUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		System.out.println("进入了VolidateAuthCodeUsernamePasswordAuthenticationFilter" + request.getParameter("j_username"));
		//这里可以进行验证验证码的操作
		
		return super.attemptAuthentication(request, response);
	}

}

需要配置一个LoginUrlAuthenticationEntryPoint bean

	<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<property name="loginFormUrl" value="/login.jsp"></property>
	</bean>

配置过滤器bean

	<!-- 验证码过滤器 -->
	<bean id="validateCodeAuthenticationFilter"
		class="com.zf.myfilter.VolidateAuthCodeUsernamePasswordAuthenticationFilter">
		<property name="authenticationSuccessHandler"
			ref="loginLogAuthenticationSuccessHandler"></property>
		<property name="authenticationFailureHandler"
			ref="simpleUrlAuthenticationFailureHandler"></property>
		<property name="authenticationManager" ref="authenticationManager"></property>
	</bean>

	<!-- 登录成功 -->
	<bean id="loginLogAuthenticationSuccessHandler"
		class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
		<property name="defaultTargetUrl" value="/index.jsp"></property>
	</bean>

	<!-- 登录失败 -->
	<bean id="simpleUrlAuthenticationFailureHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<property name="defaultFailureUrl" value="/index.jsp?error=true"></property>
	</bean>

将 <http> 中的auto-config 属性删除。加上 entry-point-ref="authenticationProcessingFilterEntryPoint" 属性

并将<form-login> 删除,使用<security:custom-filter
ref="validateCodeAuthenticationFilter"  position="FORM_LOGIN_FILTER"
/> 替代 FORM_LOGIN_FILTER拦截器


完整的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:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
			http://www.springframework.org/schema/security 
			http://www.springframework.org/schema/security/spring-security-3.1.xsd">

	<!-- 启用注解方式对方法的权限控制 -->
	<security:global-method-security
		pre-post-annotations="enabled" secured-annotations="enabled"
		jsr250-annotations="enabled" proxy-target-class="true">
		<security:protect-pointcut access="VIP"
			expression="execution(* com.zf.service.VipService.*(..))" />
	</security:global-method-security>

	<!--use-expressions="true" 的意思是开启表达式 access-denied-page的意思是,当验证权限失败后会跳转到的页面 -->
	<security:http use-expressions="true" access-denied-page="/powermiss.jsp" entry-point-ref="authenticationProcessingFilterEntryPoint">
		<!-- 对登录页面,所有的用户都可以访问 -->
		<security:intercept-url pattern="/login.jsp*"
			access="permitAll" />
		<security:intercept-url pattern="/vip.jsp*"
			access="hasRole('VIP')" />
		<security:intercept-url pattern="/admin.jsp*"
			access="hasRole('ADMIN')" />
		<!-- 对所有的资源,都必须要有COMM权限 才可以访问 -->  
		<security:intercept-url pattern="/*"
			access="hasRole('COMM')" />
			
		<!-- 使用自己的过滤器 -->
		<!-- 下面的配置表示将自己的过滤器放在FORM_LOGIN_FILTER过滤链的最前面(可以这样来验证登录验证码) -->
		<security:custom-filter
			ref="validateCodeAuthenticationFilter"  position="FORM_LOGIN_FILTER"
			 />
			
		<!-- 配置登录页面为login.jsp ,登录成功默认跳转到index.jsp,登录失败返回login.jsp并携带参数error=true -->
<!-- 		<security:form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" />  -->
		
		<!-- 退出配置 -->
		<security:logout invalidate-session="true"
			logout-success-url="/login.jsp" logout-url="/auth/logout" />

	</security:http>
	
	
	<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<property name="loginFormUrl" value="/login.jsp"></property>
	</bean>

	<!-- 验证码过滤器 -->
	<bean id="validateCodeAuthenticationFilter"
		class="com.zf.myfilter.VolidateAuthCodeUsernamePasswordAuthenticationFilter">
		<property name="authenticationSuccessHandler"
			ref="loginLogAuthenticationSuccessHandler"></property>
		<property name="authenticationFailureHandler"
			ref="simpleUrlAuthenticationFailureHandler"></property>
		<property name="authenticationManager" ref="authenticationManager"></property>
	</bean>

	<!-- 登录成功 -->
	<bean id="loginLogAuthenticationSuccessHandler"
		class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
		<property name="defaultTargetUrl" value="/index.jsp"></property>
	</bean>

	<!-- 登录失败 -->
	<bean id="simpleUrlAuthenticationFailureHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<property name="defaultFailureUrl" value="/index.jsp?error=true"></property>
	</bean>


	<!-- 配置一个认证管理器 -->
	<security:authentication-manager alias="authenticationManager">
		<!-- 使用自定义的UserDetailService -->
		<security:authentication-provider
			user-service-ref="ETUserDetailService">
			<!-- 下面的内容就可注释掉了 -->
			<!-- <security:user-service> -->
			<!-- 这样的配置表示向系统中添加了一个用户 用户名和密码都为admin ,并且该用户拥有ROLE_USER角色(角色可以用逗号隔开) -->
			<!-- <security:user name="admin" password="admin" authorities="ROLE_USER"/> -->
			<!-- </security:user-service> -->
		</security:authentication-provider>
	</security:authentication-manager>


</beans>




SPEL 表达式 

	//拥有DISUSER_PUBLISH_ROOM一个权限就可以访问
//	@PreAuthorize("hasRole('DISUSER_PUBLISH_ROOM')")
	
	//拥有DISUSER_PUBLISH_ROOM、DISUSER_MODIFY_ROOM中任意一个权限即可访问
	@PreAuthorize("hasAnyRole('DISUSER_PUBLISH_ROOM','DISUSER_ADMIN')") 
	// or
//	@PreAuthorize("hasRole('DISUSER_PUBLISH_ROOM') or hasRole('DISUSER_MODIFY_ROOM')")
	
	//必须同时拥有DISUSER_PUBLISH_ROOM、DISUSER_MODIFY_ROOM两个权限才可以访问
    //@PreAuthorize("hasRole('DISUSER_PUBLISH_ROOM') and hasRole('DISUSER_MODIFY_ROOM')")





未完待续》。。

你可能感兴趣的:(使用spring-security3.1 + spring mvc + Hibernate 控制系统权限)