第一步
下载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
<?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>
<?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>
<%@ 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>
然后就可以测试访问了。
使用注解方式对指定的方法进行权限控制
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(); /* 上面的两种注解都可以 */ }
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 ; } }
<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); } }
<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>
并将<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')")
未完待续》。。