Servlet会话跟踪基础

会话跟踪技术

HTTP 是一种“无状态”协议。也就是说:当一个请求响应结束后,不会留下任何痕迹。或者说:下一次请求响应不会获得上一次请求响应的任何信息。

但是,从开发角度考虑,我们希望上一次请求所传递的数据能够维持状态到下一次请求,并且辨认出是否相同的客户端所发送出来的

会话跟踪技术解决方案有:

  1. Cookie
  2. Session
  3. URL重写
  4. 隐藏表单域

Cookie

Cookie由服务器生成,然后发送给客户端浏览器,浏览器会将 Cookie保存到客户端内存中或者保存到客户端某个目录下的文本文件内。下次请求同一网站时就发送该 Cookie给 服务器

前端index.html文件

<h3>登陆</h3>
<form action="http://localhost:8080/demo/login" method="post">
  用户名:<input type="text" name="userName"><br>
  密码:<input type="password" name="password"><br>
  <input type="submit">
</form>    
<a href="http://localhost:8080/demo/login">自动登陆</a>

 服务器端LoginServlet.java文件

package servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
@WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            response.setHeader("Access-Control-Allow-Origin", "*"); 
            boolean isLogin = false;
            //获取从客户端发送过来的Cookie(获取的是一个Cookie数组)
            Cookie[] cookieArr = request.getCookies();
            if(cookieArr!=null) {
                //遍历每一个cookie的名称(使用getName()方法)
                for(Cookie cookie : cookieArr) {
                    if(cookie.getName().equals("user")) {
                        System.out.println("自动登陆成功");
                        isLogin = true;
                    }
                }
            }
            if(!isLogin) {
                String userName = request.getParameter("userName");
                String password = request.getParameter("password");
                if(userName.equals("test")&&password.equals("111")) {
                    System.out.println("登陆成功");
                    //创建用户信息Cookie
                    Cookie userCookie = new Cookie("user","ok");
                    //设置Cookie过期时间为一周
                    userCookie.setMaxAge(24*60*60); 
                    //向客户端发生Cookie
                    response.addCookie(userCookie);
                }else {
                    System.out.println("登陆失败");
                }
            }
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            doGet(request,response);
        }
    }

cookie的缺点

cookie的缺点 :

  1. cookie安全性不够高;
  2. cookie可能被禁用;
  3. cookie存储空间很小(只有4–10KB左右)

Session

Cookie虽然在持久保存(可以设置过期时间)客户端数据提供了方便,但在一个会话范围内维持状态却并无优势。所以,在基于Cookie的基础上,出现了Session技术。

Session较为典型的应用就是:当第一次登陆成功后,一个会话开始。在这个会话范围内,可以依靠Session维护登陆状态,直到此会话结束

Session原理

使用Session维护一个会话的登陆状态:

  1. 当第一次请求时,在服务器端创建一个Session对象,并且为此对象生成一个sessionId。
  2. 同时,使用Cookie将此sessionId返回给客户端,并存储在客户端的Cookie中。
  3. 当客户端发起下一次请求时,必须携带此sessionId发送给服务器端。
  4. 服务器端根据接收的sessionId,就能找回Session对象,从而获取了上一次请求的信息

前端Login.vue文件

<template>
  <div>
    <h3>登陆</h3>
    用户名:<input type="text" v-model="userName"><br>
    密码:<input type="password" v-model="password"><br>
    <button @click="login">登陆</button>
  </div>
</template>
<script>
  export default {
    name: 'Login',
    data() {
      return {
        userName: '',
        password: ''
      }
    },
    methods: {
      login() {
        this.$axios.post('http://localhost:8080/hello/login', this.$qs.stringify({
          userName: this.userName,
          password: this.password
        })).then((response) => {
          if (response.data == 'ok') {
            this.$router.push('/news');
          } else {
            alert('用户名或密码错误!');
          }
        }).catch((error) => {
          console.log(error);
        });
      }
    }
  }
</script>

前端New.vue文件

<template>
  <div class="about">
    <button @click="news">news</button>
  </div>
</template>
<script>
  export default {
    name: 'News',
    methods:{
      news(){
        this.$axios.get('http://localhost:8080/hello/news')
          .then((response)=> {
            if (response.data == 'Not logged in') {
              alert('未登录!');
              this.$router.push('/login');
            } else {
              alert('news');
            }
          }).catch((error)=> {
            console.log(error);
          });
      }
    }
  }
</script>

 服务器端LoginServlet.java文件

package servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Cookie;
import java.io.PrintWriter;
@WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            //开启Cookie后,不能再使用* (这里使用request.getHeader("Origin")获取前端域)
            response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
            //设置开启Cookie
            response.setHeader("Access-Control-Allow-Credentials", "true");
            PrintWriter out = response.getWriter();
            HttpSession session = request.getSession();
            System.out.println(session.getId());
            String userName = request.getParameter("userName");
            String password = request.getParameter("password");
            if(userName.equals("test")&&password.equals("111")) {
                session.setAttribute("user","userInfo");
                out.print("ok");
            }else {
                out.print("error");
            }
            out.close();
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            doGet(request,response);
        }
    }

服务端NewServlet.java文件

package servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Cookie;
import java.io.PrintWriter;
@WebServlet("/news")
    public class NewsServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Credentials", "true");
            PrintWriter out = response.getWriter();
            HttpSession session = request.getSession();
            System.out.println(session.getId());
            String user = (String)session.getAttribute("user");
            if(user!=null) {
                //做news业务处理
                out.print("news");
            }else {
                out.print("Not logged in");
            }
            out.close();
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
            doGet(request,response);
        }
    }

Session的创建与销毁

  1. Session的创建: 当第一次访问Servlet时,Servlet会自动创建Session对象。可以使用request.getSession() 方法获取此Session对象。getSession()方法有两个重载:
    1. getSession() 没有参数:如果存在一个Session对象,就使用此对象;否则就创建新的Session对象。
    2. getSession(boolean) 有一个布尔类型参数:
      true:等同于 getSession()
      false:如果不存在一个Session对象,就返回null
  1. Session的销毁:Session对象的销毁分为三种情况:
    1. Session对象的失效: 如果浏览器始终不关闭,那么就是说:客户端始终能带着sessionID去请求,那么将能够获取以前的session对象。但是如果浏览器被关闭,那服务器端就不能找到以前的session对象。以前的session对象将永远的丢失。session对象就相当于失效了。此时,服务器端会创建新的session对象。
    2. Session对象的主动销毁: session.invalidate();
    3. Session对象的超时销毁: 服务器自动在一定间隔时间内,将不再被访问session自动销毁。 比如:在web.xml写入如下配置:
<session-config>
  <!-- 单位是分钟 -->
  <session-timeout>30</session-timeout>
</session-config>

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值