陈建华的博客
专注web开发
使用spring-security3.1 + spring mvc + Hibernate 控制系统权限
2014-07-01 09:30:49   阅读2456次

第一步

下载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>

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

1358176507_8814.jpg

然后就可以测试访问了。

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

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')")



-----------------------------------------------------
转载请注明来源此处
原地址:#

-----网友评论----
暂无评论
-----发表评论----
微网聚博客乐园 ©2014 blog.mn886.net 鲁ICP备14012923号   网站导航