1、会话跟踪技术的概述
-
会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束
在一次会话中可以包含多次请求和响应。- 从浏览器发出请求到服务端响应数据给前端之后,一次会话(在浏览器和服务器之间)就被建立了
- 会话被建立后,如果浏览器或服务端都没有被关闭,则会话就会持续建立着
- 浏览器和服务器就可以继续使用该会话进行请求发送和响应,上述的整个过程就被称之为会话
-
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据
- 服务器会收到多个请求,这多个请求可能来自多个浏览器
- 服务器需要用来识别请求是否来自同一个浏览器
- 服务器用来识别浏览器的过程,这个过程就是会话跟踪
- 服务器识别浏览器后就可以在同一个会话中多次请求之间来共享数据
-
会话跟踪技术实现方式
(1)客户端会话跟踪技术:Cookie
(2)服务端会话跟踪技术:Session
2、Cookie
-
Cookie的基本使用
- Cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问。
- Cookie的基本使用
- 发送Cookie
(1)创建Cookie对象,并设置数据
(2)发送Cookie到客户端:使用response对象Cookie cookie = new Cookie("key","value");
response.addCookie(cookie);
- 获取Cookie
(1)获取客户端携带的所有Cookie,使用request对象
(2)遍历数组,获取每一个Cookie对象:for
(3)使用Cookie对象方法获取数据Cookie[] cookies = request.getCookies(); cookie.getName(); cookie.getValue();
- 发送Cookie
-
Cookie的原理分析
对于Cookie的实现原理是基于HTTP协议的,其中设计到HTTP协议中的两个请求头信息:- 响应头:set-cookie
- 请求头: cookie
-
Cookie的使用细节
-
Cookie的存活时间
- (1)默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁
- (2)Cookie持久化存储:设置Cookie存活时间
setMaxAge(int seconds)
参数值为:
1.正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
2.负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
3.零:删除对应Cookie
//发送Cookie //1. 创建Cookie对象 Cookie cookie = new Cookie("username","zs"); //设置存活时间 ,1周 7天 cookie.setMaxAge(60*60*24*7); //易阅读,需程序计算 //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算 //2. 发送Cookie,response response.addCookie(cookie);
-
Cookie存储中文
- (1)Cookie不能直接存储中文
- (2)进行转码:
URL编码
//发送Cookie String value = "张三"; //对中文进行URL编码 value = URLEncoder.encode(value, "UTF-8"); System.out.println("存储数据:"+value); //将编码后的值存入Cookie中 Cookie cookie = new Cookie("username",value); //设置存活时间 ,1周 7天 cookie.setMaxAge(60*60*24*7); //2. 发送Cookie,response response.addCookie(cookie);
//获取Cookie //1. 获取Cookie数组 Cookie[] cookies = request.getCookies(); //2. 遍历数组 for (Cookie cookie : cookies) { //3. 获取数据 String name = cookie.getName(); if("username".equals(name)){ String value = cookie.getValue();//获取的是URL编码后的值 %E5%BC%A0%E4%B8%89 //URL解码 value = URLDecoder.decode(value,"UTF-8"); System.out.println(name+":"+value);//value解码后为 张三 break; } }
-
3、Session
-
Session的基本使用
- Session:服务端会话跟踪技术:将数据保存到服务端
- Session的基本使用
- 获取Session对象,使用的是request对象
HttpSession session = request.getSession();
- Session对象提供的功能:
(1)存储数据到 session 域中
(2)根据 key,获取值
(3)根据 key,删除该键值对void setAttribute(String name, Object o) Object getAttribute(String name) void removeAttribute(String name)
- 获取Session对象,使用的是request对象
-
Session的原理分析
- Session是基于Cookie实现的
- Session是基于Cookie实现的
-
Session的使用细节
- Session钝化与活化
- 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
- 活化:再次启动服务器后,从文件中加载数据到Session中
- 注意:
- session数据存储在服务端,服务器重启后,session数据会被保存
- 浏览器被关闭启动后,重新建立的连接就已经是一个全新的会话,获取的session数据也是一个新的对象
- session的数据要想共享,浏览器不能关闭,所以session数据不能长期保存数据
- cookie是存储在客户端,是可以长期保存
- Session销毁
- 默认情况下,无操作,30分钟自动销毁
可以通过项目的web.xml进行配置
<session-config> <session-timeout>100</session-timeout> </session-config>
- 调用Session对象的invalidate()进行销毁
- 默认情况下,无操作,30分钟自动销毁
- Session钝化与活化
4、对比Cookie和Session
- 区别:
- 存储位置:Cookie 是将数据存储在客户端,Session 将数据存储在服务端
- 安全性:Cookie不安全,Session安全
- 数据大小:Cookie最大3KB,Session无大小限制
- 存储时间:Cookie可以通过setMaxAge()长期存储,Session默认30分钟
- 服务器性能:Cookie不占服务器资源,Session占用服务器资源
- 应用场景:
- 购物车:使用Cookie来存储
- 以登录用户的名称展示:使用Session来存储
- 记住我功能:使用Cookie来存储
- 验证码:使用session来存储
- 结论
- Cookie是用来保证用户在未登录情况下的身份识别
- Session是用来保存用户登录后的数据
5、用户登录注册案例
-
需求
- 完成用户登录功能,如果用户勾选“记住用户” ,则下次访问登录页面自动填充用户名密码
- 完成注册功能,并实现验证码功能
-
用户登录功能
LoginServlet类@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { private UserService service = new UserService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //2. 调用service查询 User user = service.login(username, password); //3. 判断 if(user != null){ //登录成功,跳转到查询所有的BrandServlet //将登陆成功后的user对象,存储到session HttpSession session = request.getSession(); session.setAttribute("user",user); String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/selectAllServlet"); }else { // 登录失败, // 存储错误信息到request request.setAttribute("login_msg","用户名或密码错误"); // 跳转到login.jsp request.getRequestDispatcher("/login.jsp").forward(request,response); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
记住我-设置Cookie
//判断用户是否勾选记住我,字符串写前面是为了避免出现空指针异常 if("1".equals(remember)){ //勾选了,发送Cookie //1. 创建Cookie对象 Cookie c_username = new Cookie("username",username); Cookie c_password = new Cookie("password",password); // 设置Cookie的存活时间 c_username.setMaxAge( 60 * 60 * 24 * 7); c_password.setMaxAge( 60 * 60 * 24 * 7); //2. 发送 response.addCookie(c_username); response.addCookie(c_password); }
-
记住我-获取Cookie
<form action="/brand-demo/loginServlet" method="post" id="form"> <h1 id="loginMsg">LOGIN IN</h1> <div id="errorMsg">${login_msg}</div> <p>Username:<input id="username" name="username" value="${cookie.username.value}" type="text"></p> <p>Password:<input id="password" name="password" value="${cookie.password.value}" type="password"></p> <p>Remember:<input id="remember" name="remember" value="1" type="checkbox"></p> <div id="subDiv"> <input type="submit" class="button" value="login up"> <input type="reset" class="button" value="reset"> <a href="register.html">没有账号?</a> </div> </form>
-
用户注册功能
-
验证码-展示
- 验证码的生成是通过工具类来实现的
- 验证码就是使用Java代码生成的一张图片
- 验证码的作用:防止机器自动注册,攻击服务器
(1)修改Register.jsp页面,将验证码的图片从后台获取
<tr> <td>验证码</td> <td class="inputs"> <input name="checkCode" type="text" id="checkCode"> <img id="checkCodeImg" src="/brand-demo/checkCodeServlet"> <a href="#" id="changeImg" >看不清?</a> </td> </tr> <script> document.getElementById("changeImg").onclick = function () { //路径后面添加时间戳的目的是避免浏览器进行缓存静态资源 document.getElementById("checkCodeImg").src = "/brand-demo/checkCodeServlet?"+new Date().getMilliseconds(); } </script>
(2)编写CheckCodeServlet类,用来接收请求生成验证码
@WebServlet("/checkCodeServlet") public class CheckCodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 生成验证码 ServletOutputStream os = response.getOutputStream(); String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, os, 4); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
验证码-校验