[本系列文章是博主的学习笔记,而非经典教程,特此说明]
在Web开发中,我们经常遇到的一个概念就是Session。本文我们首先来简单介绍一下Session的基本内容及用法。再来介绍shiro中如何使用Session。
准备工作:
1.操作系统:win7 x64
2.开发工具:myeclipse 2014,jdk1.7,maven3.3.3,tomcat7,jsp基础
-----------------------------------------------------------------------------------------------------------------------------------------------------------
正文开始:
一.示例程序
1.创建shiro06工程,工程结构如下图:【博主直接从shiro05工程复制过来,下图所示的文件中有冗余,请读者按需创建即可】
2.pom文件在本文示例中不用修改
3.修改LoginServlet.java文件,具体内容如下:
package shiro05; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; /** *@author 作者 E-mail: *@version 创建时间:2016年2月12日下午4:24:21 *类说明 */ public class LoginServlet extends HttpServlet{ /** * */ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("login doget"); req.getRequestDispatcher("login.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("login dopost"); String username= req.getParameter("username"); String password=req.getParameter("password"); Subject sub = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username,password); try { sub.login(token); Session session = sub.getSession(); System.out.println(session.getId()); System.out.println(session.getHost()); System.out.println(session.getTimeout()); session.setAttribute("info", "session-info"); resp.sendRedirect("success.jsp"); } catch (AuthenticationException e) { // TODO Auto-generated catch block e.printStackTrace(); req.setAttribute("errorInfo","用户名密码错误"); req.getRequestDispatcher("login.jsp").forward(req, resp); } } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${info} 欢迎您 <shiro:hasRole name="admin"> 欢迎有admin角色的用户 <shiro:principal/> </shiro:hasRole> <shiro:hasPermission name="student:create"> 欢迎有student:create权限的用户 </shiro:hasPermission> </body> </html>5.启动tomcat,在浏览器中观察success.jsp页面返回的结果。
上面我们简单演示了shiro中session的使用,由于不同的开发环境下对于session及其他解决方案的选择不同,我们在此就不再过多演示其他session方法,有兴趣的读者可以访问官方文档中进行查看。下面我们列举出常用的session对象方法,供读者参考:
方法名称 | 描述 | 返回值 |
---|---|---|
getAttribute(Object key) | 根据key标识返回绑定到session的对象 | Object |
getAttributeKeys() | 获取在session中存储的所有的key | Collection<Object> |
getHost() | 获取当前主机ip地址 | String |
getId() | 获取session的唯一id | Serializable |
getLastAccessTime() | 获取最后的访问时间 | Date |
getStartTimestamp() | 获取session的启动时间 | Date |
getTimeout() | 获取session失效时间,单位毫秒 | long |
setTimeout(long maxIdleTimeInMillis) | 设置session的失效时间 | void |
removeAttribute(Object key) | 通过key移除session中绑定的对象 | Object |
setAttribute(Object key, Object value) | 设置session会话属性 | void |
stop() | 销毁会话 | void |
touch() | 更新会话最后访问时间 | void |
二.shiro中的会话管理
1.什么是Session
在Web中,服务器可以为每一个用户的浏览器创建一个会话对象(即Session对象)。Session对象等价于一个临时容器,保存着用户从登陆服务器开始至用户退出服务器这一段时间范围内的用户基本信息和其他新增信息。这个信息能够被用户在通过浏览器访问其他程序时使用。换一种方式来理解:我们经常在购物网站上使用的“购物车”就可以理解为一个“Session”,这个"购物车"中保存着我们的基本信息如用户名等,我们随时“新增的商品”可以理解为其他新增信息。当在多个商品页面切换时,购物车的信息一直保存并且可以随时更改。最后当我们在提交订单页面提交订单时,可以理解为用户通过浏览器访问其他程序。这时“购物车”的信息被新的应用程序所使用。即Session信息可以被别的应用程序调用。具体使用方式件上文的示例程序。这里我们仅仅展示了其中一些方法,更多内容请查看官方文档进行学习与使用。
特别注意的是:
a.Session具有时间上的概念,即在浏览器访问启动时---浏览器访问退出时
b.Session是独占式的,即A,B两个用户访问服务器时,其Session是不同的
c.Session的存放位置:保存在服务器端,同时,又通过特殊的形式保存在客户端中
2.shiro中的会话
shiro提供了完整的会话功能,如:会话管理,会话监听,会话存储,失效过期,单点登陆等等,并且这些功能不依赖于底层容器(如tomcat)。我们可以使用shiro提供的功能来替代web容器的会话管理。在这里我们来解释一下“会话”的概念:会话即是用户访问应用时保持的链接关系,在多次交互中应用能够识别出当前访问的用户是谁,且可以在多次交互中保存一些数据。
3.会话管理器
shiro的会话管理器管理着会话的创建,维护,删除,失效,验证等,是shiro的核心组件。shiro中提供了三个默认实现,分别为:a.DefaultSessionManager:DefaultSecurityManager使用的默认实现,用于JavaSE 环境;
b.ServletContainerSessionManager:DefaultWebSecurityManager使用的默认实现,用于Web环境,其直接使用Servlet 容器的会话;
c.DefaultWebSessionManager : 用于Web 环境的实现, 可以替代ServletContainerSessionManager,自己维护着会话,直接废弃了Servlet容器的会话管理。
这里我们使用b选项,其已经能够满足我们基本的web开发需求。
4.会话监听
会话监听用于监听会话创建,过期及停止事件。
在此我们以上面的工程为基础。修改配置文件为如下内容:
[main] authc.loginUrl=/login roles.unauthorizedUrl=/unauthorized.jsp perms.unauthorizedUrl=/unauthorized.jsp securityManager.sessionMode=native aSessionListener = shiro05.MySessionListener securityManager.sessionManager.sessionListeners = $aSessionListener [users] shiro05=1234,admin shiro051=1234,teacher shiro052=1234 [roles] admin=user:* teacher=student:* [urls] /login=anon /admin*/**=authc /student=roles[teacher] /teacher=perms["user:create"]再创建自定义的MySessionListener.java文件,具体内容如下:
package shiro05; import org.apache.shiro.session.Session; import org.apache.shiro.session.SessionListener; /** *@author 作者 E-mail: *@version 创建时间:2016年2月13日上午9:42:15 *类说明 */ public class MySessionListener implements SessionListener{ public void onExpiration(Session session) { System.out.println("会话过期:" + session.getId()); } public void onStart(Session session) { System.out.println("会话过期:" + session.getId()); } public void onStop(Session session) { System.out.println("会话停止:" + session.getId()); } }
最后,运行程序,用户登陆之后,查看控制台输出结果即可。
如果只想监听某一个事件,可以继承SessionListenerAdapter实现:
首先修改shiro配置文件为如下内容:
[main] authc.loginUrl=/login roles.unauthorizedUrl=/unauthorized.jsp perms.unauthorizedUrl=/unauthorized.jsp securityManager.sessionMode=native aSessionListener = shiro05.MySessionListener bSessionListener = shiro05.MySessionListener2 securityManager.sessionManager.sessionListeners = $aSessionListener,$bSessionListener [users] shiro05=1234,admin shiro051=1234,teacher shiro052=1234 [roles] admin=user:* teacher=student:* [urls] /login=anon /admin*/**=authc /student=roles[teacher] /teacher=perms["user:create"]再创建自定义的MySessionListener2.java文件,具体内容如下:
package shiro05; import org.apache.shiro.session.Session; import org.apache.shiro.session.SessionListenerAdapter; /** *@author 作者 E-mail: *@version 创建时间:2016年2月13日上午11:42:26 *类说明 */ public class MySessionListener2 extends SessionListenerAdapter { public void onStart(Session session) { System.out.println("单个监听会话过期:" + session.getId()); } }最后,运行程序,用户登陆之后,查看控制台输出结果即可。
-----------------------------------------------------------------------------------------------------------------------------------------------
至此,shiro入门实战笔记(9)--会话管理结束
备注:
由于会话管理功能在实际开发中项目需求各有差异,并且博主还未做深入研究。对于这部分内容,待有实际应用和深入理解之后再更新,敬请期待!
参考资料:
官方文档:http://shiro.apache.org/documentation.html
其他博文:http://jinnianshilongnian.iteye.com/blog/2018936