JavaWeb之JSP、Cookie、Session

admin 2024年9月10日23:40:57评论25 views字数 10837阅读36分7秒阅读模式
声明:请勿利用本公众号文章内的相关技术、工具从事非法测试,如因此造成一切不良后果与文章作者及本公众号无关!

前两篇介绍了JavaWeb的一些基础知识,需要了解的可以通过下面链接查阅:

JavaWeb之HTTP、Tomcat、Servlet

0xNvyao,公众号:安全随笔JavaWeb之HTTP、Tomcat、Servlet

JavaWeb之Request请求和Response响应

0xNvyao,公众号:安全随笔JavaWeb之Request请求和Response响应

本节继续来分享JavaWeb知识,说一说JSP和Java的会话技术(Cookie、Session)

目录:
0x01,JSP介绍及原理
    -- JSP简介
    -- JSP简单入门
    -- JSP原理介绍
0x02,JSP脚本
    -- JSP 脚本形式
    -- JSP EL表达式
    -- JSP JSTL标签
0x03,会话跟踪技术
    -- Cookie
    -- Session

0x01,JSP介绍及原理

JSP简介

摘自ChatGPT:JSP(JavaServer Pages)是一种用于构建动态Web页面的Java 技术。它允许开发人员在HTML页面中嵌入Java代码,使其更易于生成动态内容、访问数据库、执行业务逻辑等。当JSP页面被请求时,服务器会将其转换为Servlet,并最终生成HTML响应发送给客户端浏览器。JSP提供了一种简单且强大的方式来创建交互式的Web应用程序。

现在几乎没有公司会用JSP了(除了安全研究,还有P用么),更好的架构是前后端分离技术,但是为啥当初会产生JSP技术呢?我想原因不外乎:

  • 早期互联网对动态Web页面的需求

  • 前后段分离架构/思想还不是主流

在这个背景下,就出现了HTML+Java柔和在一起的JSP技术,这个在当时那个年代确实是一个创新和技术突破,不过随着技术的不断更新迭代,目前前后端分离架构更符合现在的软件开发模式。

JSP简单入门

编写JSP代码分为三步:

1)添加JSP依赖

  <dependencies>    <dependency>      <groupId>javax.servlet</groupId>      <artifactId>javax.servlet-api</artifactId>      <version>3.1.0</version>      <scope>provided</scope>    </dependency>    <!--jsp依赖-->    <dependency>      <groupId>javax.servlet.jsp</groupId>      <artifactId>jsp-api</artifactId>      <version>2.1</version>      <scope>provided</scope>    </dependency>  </dependencies>

2)创建JSP页面

在Maven工程的webapp目录下创建jsp文件:

JavaWeb之JSP、Cookie、Session

3)编写HTML+Java代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>JSP入门</title></head><body>    <h1>一个JSP入门Demo</h1>    <%        System.out.println("当控制台看到这行打印,说明JSP页面中的java代码被执行了~~~");    %></body></html>

运行访问hello.jsp看效果:

JavaWeb之JSP、Cookie、Session

JSP原理介绍

前面JSP简介说到,当JSP页面被请求时,服务器会将其转换为Servlet,并最终生成HTML响应发送给客户端浏览器。其实这句话就是JSP的原理,不过我们要通过源码看一下:

1)找到上面写的hello.jsp转换后的hello_jsp.java,位于打包目录下

JavaWeb之JSP、Cookie、Session

2)hello_jsp.java的完整代码

注意:public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase

/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/7.0.47 * Generated at: 2024-09-05 09:07:52 UTC * Note: The last modified time of this file was set to *       the last modified time of the source file after *       generation to assist with modification tracking. */package org.apache.jsp;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase    implements org.apache.jasper.runtime.JspSourceDependent {  private static final javax.servlet.jsp.JspFactory _jspxFactory =          javax.servlet.jsp.JspFactory.getDefaultFactory();  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;  private javax.el.ExpressionFactory _el_expressionfactory;  private org.apache.tomcat.InstanceManager _jsp_instancemanager;  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {    return _jspx_dependants;  }  public void _jspInit() {    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());  }  public void _jspDestroy() {  }  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)        throws java.io.IOException, javax.servlet.ServletException {    final javax.servlet.jsp.PageContext pageContext;    javax.servlet.http.HttpSession session = null;    final javax.servlet.ServletContext application;    final javax.servlet.ServletConfig config;    javax.servlet.jsp.JspWriter out = null;    final java.lang.Object page = this;    javax.servlet.jsp.JspWriter _jspx_out = null;    javax.servlet.jsp.PageContext _jspx_page_context = null;    try {      response.setContentType("text/html;charset=UTF-8");      pageContext = _jspxFactory.getPageContext(this, request, response,            null, true, 8192, true);      _jspx_page_context = pageContext;      application = pageContext.getServletContext();      config = pageContext.getServletConfig();      session = pageContext.getSession();      out = pageContext.getOut();      _jspx_out = out;      out.write("n");      out.write("n");      out.write("<html>n");      out.write("<head>n");      out.write("    <title>JSP入门</title>n");      out.write("</head>n");      out.write("<body>n");      out.write("    <h1>一个JSP入门Demo</h1>n");      out.write("    ");        System.out.println("当控制台看到这行打印,说明JSP页面中的java代码被执行了~~~");      out.write("n");      out.write("</body>n");      out.write("</html>n");    } catch (java.lang.Throwable t) {      if (!(t instanceof javax.servlet.jsp.SkipPageException)){        out = _jspx_out;        if (out != null && out.getBufferSize() != 0)          try { out.clearBuffer(); } catch (java.io.IOException e) {}        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);        else throw new ServletException(t);      }    } finally {      _jspxFactory.releasePageContext(_jspx_page_context);    }  }}

3)org.apache.jasper.runtime.HttpJspBase源码

注意:public abstract class HttpJspBase extends HttpServlet implements HttpJspPage

JavaWeb之JSP、Cookie、Session

4)然后仔细看上面转换的hello_jsp.java的源码

里面也包含_jspInit()、_jspService()、_jspDestroy()三个方法,这个和Servlet接口的方法类似。其中_jspService()是由容器生成并调用的一个方法,它是JSP页面被转换成Servlet之后的核心方法之一。

分析到这就清楚了,真正给浏览器响应的不是jsp页面,而是转换后的jsp servlet对象的_jspService() 方法,这个方法主要负责处理客户端的请求并生成响应。在这个方法中,容器会将生成的 Servlet 代码中插入 JSP 页面中的 Java 代码段,并将整个页面编译成 Servlet 类。当客户端请求访问这个 JSP 页面时,容器会实例化这个 Servlet 类,并调用其 _jspService() 方法来处理请求。

最后贴一张图看下hello.jsp源码和转换后的hello_jsp.java源码对比:

JavaWeb之JSP、Cookie、Session

0x02,JSP脚本

JSP脚本形式

介绍JSP脚本其实重点是介绍JSP脚本里如何定义Java代码。JSP提供了三种形式:

  • <%...%>:内容会直接放到_jspService()方法之中

  • <%=...>:内容会放到_jspService()方法的out.print()中,作为out.print()的参数

  • <%!...%>:内容会放到_jspService()方法之外,被类直接包含

看一下这样的Demo,分别包含上面三种JSP脚本形式:

<body>    <h1>一个JSP入门Demo</h1>    <%        System.out.println("当控制台看到这行打印,说明JSP页面中的java代码被执行了~~~");        int num = 100;    %>    <%!        String username = "jsp";        void myPrint(){            System.out.println(username);        }    %>    <%="hello"%>    <%=num%>    <%=username%></body>

启动项目访问一下修改后的JSP页面,然后看下转换后的hello_jsp.java文件:

JavaWeb之JSP、Cookie、Session

JavaWeb之JSP、Cookie、Session

JSP EL表达式

JSP EL表达式是JSP规范中的一个特性,用于简化在JSP页面中访问Java对象和数据的语法。EL提供了一种简洁、易读的方式来访问JavaBean组件、请求参数、会话属性等,并允许在JSP页面中执行基本的表达式和操作。

举几个例子:

<body>    <%--进行算数计算--%>    ${100+200}  <br />    <%--访问JavaBean属性--%>    ${users[1].username}    <br />    <%--调用方法--%>    ${users[1].getPassword()}   <br />    <%--操作集合列表--%>    ${users[1]} <br />    <%--EL表达式隐士对象--%>    ${header}   <br />    ${param}    <br />    <%--访问作用域对象--%>    ${requestScope}    ${requestScope.containsKey("users")}   <br />    ${requestScope.get("javax.servlet.forward.context_path")}   <br /></body>

结果:

JavaWeb之JSP、Cookie、Session

另外值得说一下的是JSP的四大作用域,分别是page、request、session、applicaiton,从左到右作用域范围一次递增,这些作用域提供了不同级别和范围的数据共享机制,例如上面通过 req.setAttribute("users", users); 给request域设置数据。

  • page:当前jsp页面有效(最小)

  • request:当前请求有效

  • session:当前回话有效

  • application:当前应用有效(最大)

JSP JSTL标签

JSP 标准标签库(JSTL)是一组自定义标签,用于简化 JSP 页面的开发。标签非常多,可以通过这里学习,这里只介绍下最重要的两个标签:c:if 和 c:forEach

JSTL标签学习

https://www.runoob.com/jsp/jsp-jstl.html

1)引入jstl坐标

<!--jstl标签库-->    <dependency>      <groupId>javax.servlet</groupId>      <artifactId>jstl</artifactId>      <version>1.1.2</version>    </dependency>    <dependency>      <groupId>taglibs</groupId>      <artifactId>standard</artifactId>      <version>1.1.2</version>    </dependency>

2)添加 JSTL(JSP Standard Tag Library)核心标签库指令

<%@ page contentType="text/html;charset=UTF-8" language="java" %># 添加下面这行指令<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head>    <title>JSTL入门</title></head>

3)编写servlet和jsp

@WebServlet("/myServlet")public class MyServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        req.setAttribute("gender", 1);        req.getRequestDispatcher("jstl-demo.jsp").forward(req, resp);}
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html><head>    <title>JSTL入门</title></head><body><%--jstl的c:if标签用于条件判断,替换java的if else--%>    <c:if test="${gender == 1}">    </c:if>    <c:if test="${gender == 0}">    </c:if></body></html>

4)访问

JavaWeb之JSP、Cookie、Session

5)再来看下 c:forEach 标签

特别适合对集合数据进行循环遍历,替代了jsp中繁琐的java代码

<body>    <%--jstl的c:forEach标签用于循环,替换java的foreach循环--%>    <c:forEach items="${users}" var="user">        <tr align="center">            <td>${user.username}</td>            <td>${user.password}</td>            <td>${user.address}</td>            <c:if test="${user.gender == 1}">                <td>男</td>            </c:if>            <c:if test="${user.gender == 0}">                <td>女</td>            </c:if>            <br />        </tr>    </c:forEach></body>

JavaWeb之JSP、Cookie、Session

0x03,会话跟踪技术

在本系列第一篇文章有介绍过HTTP协议的特点,其中重要的一点是HTTP是无状态的:

JavaWeb之JSP、Cookie、Session

在 Web 开发中,HTTP 协议是无状态的,即每个请求都是相互独立的,服务器无法直接识别来自同一用户的多个请求。为了解决这个问题,会话跟踪技术被引入,以维护用户和服务器之间的关联状态

会话跟踪技术的实现分为客户端会话跟踪技术Cookie和服务端会话跟踪技术Session,下面分别来介绍。

Cookie

Cookie应该都很熟悉了,是一种客户端会话跟踪技术,将数据保存到客户端,以后浏览器每次请求都携带Cookie数据进行访问,服务端来校验Cookie数据。

1)创建一个新的Maven Module

JavaWeb之JSP、Cookie、Session

2)编写创建Cookie的Servlet

@WebServlet("/cookie1")public class SetCookieServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 创建cookie对象        Cookie cookie = new Cookie("whoami", "zhangsan");        //2. 发送cookie        response.addCookie(cookie);    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

3)启动项目,浏览器查看set-cookie

JavaWeb之JSP、Cookie、Session

4)编写获取Cookie的Servlet

@WebServlet("/cookie2")public class GetCookieServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 获取cookie数组        Cookie[] cookies = request.getCookies();        //2. 遍历数组        for (Cookie cookie : cookies) {            //3. 获取数据            String name = cookie.getName();            if ("whoami".equals(name)) {                String value = cookie.getValue();                System.out.println(name + ":" + value);            }        }    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

5)访问/cookie2,查看浏览器携带的cookie

JavaWeb之JSP、Cookie、Session

服务端正常拿到并解析了cookie:

JavaWeb之JSP、Cookie、Session

当然cookie还有一些常用属性,这里介绍下setHttpOnly和setMaxAge:

//1. 创建cookie对象Cookie cookie = new Cookie("whoami", "zhangsan");cookie.setMaxAge(60 * 60 * 24); // 一天时间cookie.setHttpOnly(true);

JavaWeb之JSP、Cookie、Session

JavaWeb之JSP、Cookie、Session

Session

Session是服务端会话跟踪技术,将数据保存在服务端。客户端仅保存会话标识符(通过是一个Cookie)。

1)编写存储Session的Servlet

@WebServlet("/session1")public class SetSessionServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 获取Session对象        HttpSession session = request.getSession();        //2. 存储数据        session.setAttribute("whoami","i am session");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

2)编写获取Session数据的Servlet

@WebServlet("/session2")public class GetSessionServlet extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 获取Session对象        HttpSession session = request.getSession();        //2. 获取数据        Object whoami = session.getAttribute("whoami");        System.out.println(whoami);    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

3)重启服务测试

访问 /session1

JavaWeb之JSP、Cookie、Session

访问 /session2

JavaWeb之JSP、Cookie、Session

JavaWeb之JSP、Cookie、Session

最后来总结一下Session的原理,前面我们提到Session会话技术是用来解决HTTP无状态的,也就是说解决多次请求之间数据共享的问题,那么思考一下上面的Session是如何解决的呢?

其实就是一句话Session是基于Cookie实现的。

在上面的SetSessionServlet.java 和 GetSessionServlet.java 中分别打印如下内容:

System.out.println("SetSessionServlet设置的session对象地址:" + session); //打印session对象内存中的地址System.out.println("SetSessionServlet设置的session对象ID:" + session.getId());    //打印session id

然后再重启项目分别访问 /session1 和 /session2:

JavaWeb之JSP、Cookie、Session

通过打印内容可以知道:

1、会话的创建:

  • 当用户第一次访问网站时,服务器会为该用户创建一个唯一的会话ID,并将相关数据存储到会话对象中

  • 会话ID通常以Cookie的形式存储在用户的浏览器中

2、会话的跟踪:
  • 当用户在网站上浏览不同页面时,浏览器会将包含会话ID的Cookie随每个请求发送给服务器
  • 服务器通过解析会话ID,可以识别用户会话,并将用户的相关信息存储在会话对象中

在这个过程中,服务器通过会话ID来标识和区分不同用户的会话,确保用户在网站上的各个请求之间保持一致的状态。Session会话技术的实现通常依赖于服务器端的会话管理机制,用于存储和管理用户会话的相关数据。通过这种方式,同一个会话的用户可以在整个访问过程中保持一致的状态和体验。

以上本篇就介绍了JSP技术和会话管理技术,这些技术点会在后续的整合案例里面都实现一遍。

原文始发于微信公众号(安全随笔):JavaWeb之JSP、Cookie、Session

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月10日23:40:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JavaWeb之JSP、Cookie、Sessionhttps://cn-sec.com/archives/3149830.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息