JAVAEE

创建javaee项目

image-20241229093752187

image-20241229093905923

创建新项目时可以删除的内容:

image-20241230165822829

Servlet&路由&周期

https://blog.csdn.net/yxmoar/article/details/109889006

什么是Servlet

Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。本章内容详细讲解了web开发的相关内容以及servlet相关内容的配置使用,是JAVAEE开发的重中之重。

image-20241229122630025

Servlet API

image-20241229122712654

创建一个类继承HttpServlet

image-20241229123431220

web.xml配置映射关系

具体参考:https://blog.csdn.net/weixin_52937170/article/details/142183673

image-20241229123218279

当访问index时,经过路由配置访问到IndexServlet,由于是GET请求,触发了doGet方法(类似于反序列化的魔术方法)

image-20241229123558294

类似的 触发doPost方法:

image-20241229124530349

image-20241229124503897

还可以使用@WebServlet注解来配置Servlet路由(此时只需要在Servlet类前加一个@WebServlet,)

image-20241229125056350

web.xml不需要配置,但是需要保留web-app标签结构

image-20241229125108197

此时也能够正常识别路由信息

image-20241229125228202

image-20241229125235146

Servlet生命周期

image-20241229123950802

image-20241229125530421

这些方法也类似于反序列化魔术方法

处理接收和回显

HttpServletRequest(HTTP请求的信息)

  • ServletRequest的子接口:**HttpServletRequestServletRequest**接口的子接口,提供了用于处理HTTP请求的额外功能。
  • getParameter(name):通过参数名获取请求中的值。返回一个**String**,表示与给定参数名相对应的单个值。
  • getParameterValues(name):通过参数名获取请求中的多个值。返回一个**String[]**,表示与给定参数名相对应的多个值。

HttpServletResponse(HTTP响应的信息)

  • ServletResponse的子接口:**HttpServletResponseServletResponse**接口的子接口,提供了用于处理HTTP响应的额外功能。
  • setCharacterEncoding():设置响应的字符编码格式。通常用于确保正确的文本输出。
  • setContentType():设置响应内容的类型和编码。常用于指定输出的数据类型,如HTML、JSON等。
  • getWriter():获取一个**PrintWriter**字符输出流,用于向客户端发送文本数据。
  • PrintWriter:**PrintWriter**是用于向客户端输出字符数据的类,可以接受各种数据类型,然后将其转换为文本并发送到客户端。

连接数据库-JDBC&Mybatis&库

https://blog.csdn.net/xiaozhezhe0470/article/details/105420763

三种连接数据库的方法:jdbc mybatis hibernate

image-20241229104828630

现在用的最多的是mybatis

JDBC

https://www.jianshu.com/p/ed1a59750127

原生数据库开发,是由java提供的统一API接口
数据库驱动:由各个数据库厂商提供,用于访问数据库的jar包,遵循JDBC接口

下载jar

下载地址:https://mvnrepository.com/

搜索相应的数据库(比如这里是mysql),选择版本,下载jar包

引用封装jar

在目录下创建一个lib文件夹,将jar包放进去

image-20241229131711166

添加为库

image-20241229131908194

注册数据库驱动

新建一个java文件,类似于php中的连接数据库文件

Class.forName("com.mysql.jdbc.Driver");

image-20241229132546097

出现错误时可以用IDEA自动更正

image-20241229132953605

如果存在导包问题,可以直接导入 import java.sql.*;

image-20241229135100697

建立数据库连接

// 定义数据库连接的URL,格式为:jdbc:mysql://host:port/database
String url = "jdbc:mysql://localhost:3306/dome01";

// 使用DriverManager获取数据库连接
Connection connection = DriverManager.getConnection(url, "root", "root");

// 打印数据库连接信息
System.out.println(connection);

成功连接上

image-20241229133155727

如果密码失败(连接不上的情况)会产生报错

image-20241229133228367

创建Statement执行sql

image-20241229134611911

  • connection.createStatement(); 在**Connection对象上调用createStatement方法,创建一个Statement对象。Statement对象用于执行SQL语句,它可以执行静态的SQL查询、更新、删除等操作。createStatement方法返回一个新的Statement**对象。
  • 创建一个**Statement对象,然后使用该对象执行给定的SQL查询语句,将查询结果存储在一个ResultSet对象中。这样,您可以通过遍历ResultSet**来检索和处理查询的结果集中的数据。

image-20241229133738562

image-20241229133721304

ResultSet对结果进行提取

image-20241229134437962

image-20241229134255730

和数据库里的内容对应

image-20241229134413210

安全修复SQL注入:JDBC-SQL预编译

原理:提前编译好执行逻辑,你注入的语句不会改变原有逻辑

  1. 预编译写法: safesql 是一个预编译的 SQL 查询语句,其中 ? 是一个占位符,表示将在执行时动态替换。
  2. 使用 PreparedStatement PreparedStatementStatement 的子接口,用于执行预编译的 SQL 语句。通过调用 connection.prepareStatement(safesql) 创建一个 PreparedStatement 对象。
  3. 设置参数: 使用 setXXX 方法设置占位符的值。在这里,使用 setInt(1, id)id 的值设置到第一个占位符上。这种方式防止了 SQL 注入攻击,因为参数值是通过预编译的方式传递的,而不是通过直接拼接字符串。
  4. 执行查询: 调用 executeQuery() 执行查询,得到 ResultSet 对象。
  5. 处理结果集: 根据业务需要,处理查询结果集的数据。
// 预编译写法
String safesql = "SELECT * FROM news WHERE id=?";

// 使用PreparedStatement
try (PreparedStatement preparedStatement = connection.prepareStatement(safesql)) {
// 设置参数,防止SQL注入攻击
preparedStatement.setInt(1, id);

// 执行查询
ResultSet resultSet = preparedStatement.executeQuery();

// 处理结果集...
} catch (SQLException e) {
e.printStackTrace();
}

相比较于直接拼接 SQL 语句的方式,预编译语句提供了更好的安全性,可以防止SQL注入攻击。在使用预编译语句时,务必通过参数设置的方式传递值,而不要直接拼接值到 SQL 语句中。

过滤器Filter

介绍

Filter被称为过滤器,过滤器实际上就是对Web资源进行拦截,做一些处理后再交给下一个过滤器或Servlet处理,通常都是用来拦截request进行处理的,也可以对返回的 response进行拦截处理。开发人员利用filter技术,可以实现对所有Web资源的管理,例如实现权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

(考虑跟安全相关的-内存马)

image-20241229141801466

简单来说,平常的马是处于Servlet代码层面中,会以代码文件呈现,而内存马处于Listener和Filter层面中

image-20241229143655084

image-20241229143650231

过滤器来进行对xss过滤

TestServlet文件(用于接受参数code,并返回code的值到客户端)

package com.example.filterdemo1.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/test")
public class TestServlet extends HttpServlet {


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("---------doGet");
String code=req.getParameter("code");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
out.println("这是GET请求的数据");
out.println("code: "+code+"<br>");
out.flush();
out.close();
}
}

XssFilter文件(实现Filter接口中的方法)

package com.example.filterdemo1.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter("/test")
public class XssFilter implements Filter {
@Override
//中间件启动后就自动运行,无需访问路由
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("xss开启过滤");
}

@Override
//中间件关闭后就自动运行
public void destroy() {
System.out.println("xss销毁过滤");
}

@Override
//doFilter 访问路由触发的方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("xss正在过滤");
//过滤代码就应该在放行前
//如果符合就放行,不符合就过滤(拦截)
//XSS过滤 接受参数值 如果有攻击payload 就进行拦截
// 接受参数值 如果没有攻击payload 就进行放行
HttpServletRequest request= (HttpServletRequest) servletRequest;
String code = request.getParameter("code");
if(!code.contains("<script>")){ //没有攻击payload
//放行
filterChain.doFilter(servletRequest,servletResponse);
}else{
System.out.println("存在XSS攻击");
//继续拦截
}

}
}

要注意这里的TestServlet和XssFilter的路由不同,一个是@WebServlet(“/test”),一个是@WebFilter(“/test”)

中间件启动后会自动运行init,所以控制台输出xss开启过滤

image-20241229162734971

TestServlet的访问路由为test,访问test文件,触发doFilter方法,控制台打印xss正在过滤

image-20241229162816566

当我们GET方式传递code参数=1,先调用filter再调用Servlet,所以先调用XssFilter中的doFilter方法,打印xss正在过滤;再调用TestServlet中的doGet方法,控制台打印———–doGet

image-20241229162928260

当我们GET方式传递code=<script>alert(1)</script>攻击代码,由于XssFilter中检测到了<script>关键字,触发过滤,打印存在XSS攻击

image-20241229163433306

由于XssFilter中没有放行,因此TestServlet中的doGet方法不会被调用

image-20241229163319970

当我们停止时,自动调用了XssFilter中的destroy方法

image-20241229163658842

过滤器实现cookie身份验证

检测客户端的cookie的user值是否为admin

AdminServlet文件

package com.example.filterdemo1.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/admin")
public class AdminServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("欢迎进入管理员页面");
}
}

AdminFilter文件

package com.example.filterdemo1.filter;


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@WebFilter("/admin")
public class AdminFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("admin身份检测开启");
}

@Override
public void destroy() {
System.out.println("admin身份检测销毁");
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

System.out.println("admin身份检测进行");
//检测Cookie过滤
HttpServletRequest request= (HttpServletRequest) servletRequest;
Cookie[] cookies=request.getCookies();
//对Cookie进行遍历获取
for(Cookie c:cookies){
String cName = c.getName();//获取cookie名
String cValue = c.getValue();//获取cookie值
System.out.println(cName);
System.out.println(cValue);
if(cName.contains("user") && cValue.contains("admin")){
// filterChain 是一个 FilterChain 对象,代表过滤器链。
// doFilter() 方法用于将请求和响应对象传递给过滤器链中的下一个过滤器或目标资源。
// 即当前过滤通过
filterChain.doFilter(servletRequest,servletResponse);
}else {
System.out.println("非管理员访问");
}
}

}
}

开启中间件服务,调用init方法,admin身份检测开启;当我们GET访问admin时,经过AdminFilter过滤,打印我们的cookie的name和value,并且过滤name不为user,value不为admin,拦截,打印非管理员访问

image-20241229164426045

当我们添加cookie为user:admin,成功执行,进入管理员页面

image-20241229164948175

内存马技术

这里只做简单了解

img

内存马实验:

哥斯拉生成java的后门1.jsp

image-20241216163007234

用哥斯拉连接url http://localhost:8080/FilterDemo1_war_exploded/1.jsp

从而拿到shell

image-20241216163903310

这里的FilterShell就为内存马

监听器Listen

介绍

监听ServletContext、HttpSession、ServletRequest等域对象创建和销毁事件
监听域对象的属性发生修改的事件
监听在事件发生前、发生后做一些必要的处理
监听器就是用来检测的的动作,有动作就会触发监听器里的方法,不是一定要访问路由才能触发;当与监听器关联的特定事件在Web应用中发生时,监听器会被触发

监听session的创造与销毁

ListenSession文件

package com.example.listendemo1.listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener//@WebListener标记监听器类,无需路由
public class ListenSession implements HttpSessionListener {

@Override
public void sessionCreated(HttpSessionEvent se) {
//监听检测有Session创建就会执行这里
System.out.println("监听器监听到了session创建");
}//tomcat一启动,就会有session的产生,次函数就会被触发

@Override
public void sessionDestroyed(HttpSessionEvent se) {
//监听检测有Session销毁就会执行这里
System.out.println("监听器监听到了session销毁");
}
}

CSession文件(创建session)

package com.example.listendemo1.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/cs")
public class CSession extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet里面创建Session");
//创建Session
req.getSession();
}
}

DSession文件(销毁session)

package com.example.listendemo1.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebServlet("/ds")
public class DSession extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet里面销毁Session");
//销毁Session
req.getSession().invalidate();
}
}

启动时监听器监听到了, ListenSession中的sessionCreated方法就会被调用,打印监听器监听到了session创建

image-20241229165913648

当我们访问cs,调用了Servlet中CSession中的doGet方法,打印Servlet里面创建Session

image-20241229170550426

当我们访问ds,调用Servlet中DSession中的doGet方法,打印Servlet里面销毁Session,同时监听器马上就监听到了这一属性的变化,ListenSession中的sessionDestroyed方法被调用

image-20241229170802962

image-20241229170745340