java代码审计前置基础


零、前置知识

0.1 maven

Maven是基于项目对象模型(POM project object model),可以通过一小段描述信息(配置)来管理项目的构建,报告和文档的软件项目管理工具。通俗点讲,就是通过pom.xml文件的配置获取jar包,而不用手动去添加jar包。

如果需要使用pom.xml来获取jar包,那么首先该项目就必须为maven项目,maven项目可以这样去想,就是在java项目和web项目的上面包裹了一层maven,本质上java项目还是java项目,web项目还是web项目,但是包裹了maven之后,就可以使用maven提供的一些功能了(通过pom.xml添加jar包)。

XML格式显示所有依赖包的版本、名称、配置等信息。

  • 举例:
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>My Project</name>
    <url>http://example.com</url>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

0.1.1 根元素:<project>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • 定义 XML 命名空间和模式位置。

0.1.2 项目坐标(唯一标识)

<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging> <!-- 默认为 jar -->
  • **groupId**:组织/公司标识(反向域名)。
  • **artifactId**:项目名称。
  • **version**:项目版本(如 1.0-SNAPSHOT)。
  • **packaging**:打包类型(jarwarpom 等)。

0.1.3 父项目(可选)

<parent>
    <groupId>com.example.parent</groupId>
    <artifactId>parent-project</artifactId>
    <version>2.0.0</version>
    <relativePath>../parent/pom.xml</relativePath> <!-- 指定父 pom 路径 -->
</parent>
  • 用于继承父项目的配置(依赖、插件等)。

0.1.4 元数据

<name>My Project</name>
<description>示例项目</description>
<url>http://example.com</url>
<inceptionYear>2023</inceptionYear>
  • 项目描述性信息(可选)。
  • inceptionYear 元素是 project 元素下的一个子元素,用于记录项目的初始年份,通常在项目的元数据部分。

0.1.5 依赖性管理

1)直接依赖

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope> <!-- 作用域 -->
        <optional>true</optional> <!-- 可选依赖 -->
    </dependency>
</dependencies>
  • **scope**:依赖作用域(compile/test/provided/runtime)。
  • **optional**:是否作为可选依赖传递。

在Maven的依赖管理中,scopeoptional是两个重要的配置项,它们分别用于控制依赖的作用范围和依赖的传递性。下面详细解释它们的作用:

1. 依赖作用域(scope)

scope定义了依赖在项目构建生命周期中的可用性和传递性。常见的scope有以下几种:

  • compile(默认值):
    • 当没有指定scope时,默认就是compile
    • 该依赖在项目的所有classpath中可用(包括编译、测试、运行阶段)。
    • 会随着项目一起发布(例如:打包到jar、war中)。
    • 会传递给依赖该项目的其他项目(即传递性依赖)。
  • test
    • 仅用于测试阶段(编译和运行测试代码)。
    • 不会随项目发布,也不会传递给其他项目。
    • 例子:JUnit、Mockito等测试框架。
  • provided
    • 表示该依赖在编译和测试时需要,但在运行时由目标环境(如应用服务器或JDK)提供。
    • 不会随项目发布(例如:打包war时不会包含provided的依赖,因为目标环境已提供)。
    • 不会传递给其他项目。
    • 例子:Servlet API(项目运行时由Servlet容器提供)、JDBC驱动(可能由容器提供)等。
  • runtime
    • 在编译时不需要,但在运行和测试时需要。
    • 会随项目发布,并传递给其他项目。
    • 例子:JDBC驱动(编译时只需接口,运行时需要具体实现)。
  • system(不推荐):
    • provided类似,但需要显式指定本地文件路径,因此不利于移植,不推荐使用。
  • import(仅用于<dependencyManagement>中):
    • 用于从另一个pom文件中导入依赖管理配置,通常用于多模块项目或BOM(Bill of Materials)中。

总结scope的作用:

  • 控制依赖的生命周期阶段可用性:例如,测试依赖只在测试阶段可用。
  • 控制依赖的传递性:例如,testprovided范围的依赖不会传递给其他项目。
  • 控制依赖是否打包:例如,providedtest依赖不会打包到最终的部署包中。

2. 可选依赖(optional)

optional是一个布尔值(true/false),标记该依赖是否为可选依赖。

  • optional设置为true时,表示该依赖不会被传递。
  • 含义:即使项目A依赖了项目B,而项目B中有一个标记为optional=true的依赖C,那么项目A不会自动继承依赖C。项目A如果需要依赖C,必须显式声明。

2)依赖管理(<dependencyManagement>

<dependencyManagement>
    <dependencies>
        <dependency>...</dependency> <!-- 定义版本,供子模块继承 -->
    </dependencies>
</dependencyManagement>
  • 统一管理多模块项目的依赖版本。

0.1.6 构建配置(<build>

1)插件管理

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>11</source>
                <target>11</target>
            </configuration>
        </plugin>
    </plugins>
</build>
  • 配置编译、打包等插件(如 maven-surefire-plugin 用于测试)。

2)资源文件配置

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>​**​/*.properties</include>
        </includes>
    </resource>
</resources>

0.1.7 属性<properties>

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
  • 定义常量,通过 ${java.version} 引用。

0.1.8 仓库配置

<repositories>
    <repository>
        <id>my-repo</id>
        <url>https://repo.example.com</url>
    </repository>
</repositories>
<pluginRepositories>
    <!-- 插件仓库 -->
</pluginRepositories>
  • 指定依赖和插件的下载地址。

0.1.9 模块配置(多模块项目)

<modules>
    <module>module1</module>
    <module>module2</module>
</modules>
  • 定义子模块目录(用于聚合项目)。

0.1.10 maven项目创建

新建一个maven项目:

0.2 MyBatis

0.2.1 mybatis简介

MyBatis 是一个持久层框架,它就像是你和数据库之间的“翻译官”。你只需写好 SQL 语句和简单的映射规则,它就能自动把数据库里的数据变成 Java 对象,也能把 Java 对象变成数据库记录。和那些自动生成 SQL 的框架不同,MyBatis 让你完全掌控 SQL,既灵活又直接,特别适合需要精细优化 SQL 的项目。

0.2.2 用法示例

案例:一个常用的 MyBatis 例子:用户查询

假设我们有一个User表,包含id, name, email字段。

步骤:

  1. 创建对应的Java实体类User
  2. 创建Mapper接口,定义查询方法。
  3. 创建Mapper XML文件,编写SQL语句。
  4. 在MyBatis配置文件中注册Mapper。
  5. 使用SqlSession执行查询。

示例代码:

  1. 实体类:User.java
public class User {
    private int id;
    private String name;
    private String email;

    // 省略构造方法、getter和setter,但实际需要写
}
  1. Mapper接口:UserMapper.java
public interface UserMapper {
    // 根据用户ID查询用户
    User selectUser(int id);
}
  1. Mapper XML文件:UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectUser" resultType="com.example.entity.User">
        SELECT id, name, email FROM User WHERE id = #{id}
    </select>
</mapper>
  1. 使用示例
// 获取SqlSession(这里省略了SqlSessionFactory的创建过程,通常通过配置文件或Java配置)
try (SqlSession session = sqlSessionFactory.openSession()) {
    // 获取Mapper接口的代理对象
    UserMapper mapper = session.getMapper(UserMapper.class);
    // 调用方法
    User user = mapper.selectUser(1);
    System.out.println("用户信息:" + user.getName() + ", 邮箱: " + user.getEmail());
}

说明:

  • #{id}:这是MyBatis的参数占位符,相当于PreparedStatement的?,可以防止SQL注入。
  • resultType:指定查询结果映射的Java类全限定名。
  • 在MyBatis核心配置文件中需要配置数据源和映射文件的位置。

这个例子展示了MyBatis最基本的使用:通过接口绑定XML中的SQL语句,实现了简单的查询操作。

核心代码:

// 1. 定义实体类(对应数据库的user表)
public class User {
    private int id;
    private String name;
    private String email;
    // getter/setter省略
}

// 2. 创建Mapper接口(定义操作方法)
public interface UserMapper {
    // 根据id查询用户(带注释的SQL)
    @Select("SELECT * FROM user WHERE id = #{userId}")
    User selectUserById(int userId);

    // 根据姓名模糊查询(XML配置的SQL)
    List<User> selectUsersByName(String name);
}

<!-- 3. XML映射文件(实现接口方法) -->
<mapper namespace="com.example.UserMapper">
    <select id="selectUsersByName" resultType="User">
        SELECT * FROM user 
        WHERE name LIKE CONCAT('%', #{name}, '%')
    </select>
</mapper>
  
// 4. 实际使用
try (SqlSession session = sqlSessionFactory.openSession()) {
    // 直接调用接口方法(MyBatis自动实现)
    User user1 = session.getMapper(UserMapper.class).selectUserById(1001);
    
    // 执行XML映射的方法
    List<User> users = session.selectList("selectUsersByName", "张");
}

关键特点:

  1. SQL直观可见:注解和XML两种方式管理SQL语句
  2. 自动映射结果:数据库字段 → Java对象(列名匹配user_nameuserName
  3. 安全参数处理#{name} 自动防SQL注入
  4. 灵活结果处理:支持单对象、集合、Map等多种返回类型

💡 实际开发中,复杂的SQL/关联查询会用XML配置,简单查询用注解,组合使用既保持代码简洁又能应对复杂场景。

0.2.3 mybatis安装

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可。

https://blog.csdn.net/t95921/article/details/53585225 【IDEA 添加jar包到classPath】

如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:

<dependency>  
<groupId>org.mybatis</groupId>  
<artifactId>mybatis</artifactId> 
<version>x.x.x</version>
</dependency>

IDEA中安装mybatis

在【File】菜单下找到【Settings】,然后再【Plugins】下在搜索栏中输入【MyBatis Plugin】,然后点击【Install】,重启IDEA后,MyBatis插件已成功安装。

在Tools或Other中找到Config Database和 Code Generator表明安装成功。

0.3 SpringBoot

0.3.1 SpringBoot简介

SpringBoot是一款基于JAVA的开源框架。目的是为了简化Spring应用搭建和开发流程。是目前比较流行,大中小型企业常用的框架。正因为极大简化了开发流程,才收到绝大开发人员的喜爱。SpringBoot核心原理是自动装配(自动配置),在这之前,开发一个JavaWeb,Spring等项目要进行很多配置,使用了SpringBoot就不用在过多考虑这些方面。并且在SpringBoot中还内置了Tomcat。

0.3.2 SpringBoot web项目demo

1)IDEA安装SpringBoot插件

在【File】菜单下找到【Settings】,然后再【Plugins】下在搜索栏中输入【SpringBoot Assistant】,然后点击【Install】

2)创建springboot项目

创建项目并设置基础参数:

点击Next,进入依赖项选择页面,我们选择Web -> Spring Web这一个即可。

创建完的项目的初始状态:

SpringBootStuDemoApplication.java为程序入口。

⚠️:可以删掉demos.web的包,如果后续mapping的路径和这个包中的路径冲突会报错。

3)编写demo

  • HelloController
package com.sxkstu.springbootstudemo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
    @ResponseBody
    @RequestMapping("/hello")
    public String helloWorldController(){
        return "Hello SpringBoot!";
    }
}

这段代码是一个简单的 Spring Boot 控制器类,用于处理 HTTP 请求并返回响应。以下是详细解析:

1. 包声明

package com.sxkstu.springbootstudemo;
  • 定义了这个 Java 类所在的包路径(通常对应项目目录结构)

2. 导入注解

import org.springframework.stereotype.Controller;        // 声明控制器类
import org.springframework.web.bind.annotation.RequestMapping;  // 定义请求映射
import org.springframework.web.bind.annotation.ResponseBody;   // 声明直接返回响应体

3. 类定义与注解

@Controller
public class HelloController { ... }
  • **@Controller**:
    Spring MVC 的核心注解,标记该类为 Web 控制器(Controller)。Spring 启动时会扫描带有此注解的类,将其注册为 Spring 容器的 Bean。

4.方法定义与注解

@ResponseBody
@RequestMapping("/hello")
public String helloWorldController(){ ... }

核心注解说明:

  • @RequestMapping("/hello")
    • 建立 HTTP 请求路径与方法之间的映射关系。
    • 当用户访问 /hello 时(如 http://localhost:8080/hello),Spring 会调用此方法。
    • 默认响应所有 HTTP 方法(GET/POST/PUT 等)。
  • @ResponseBody
    • 表明方法返回值应直接写入 HTTP 响应体(而非视图解析)。
    • 禁用视图解析器,直接将字符串 “Hello SpringBoot!” 作为响应内容返回。

5.方法实现:

public String helloWorldController() {
    return "Hello SpringBoot!";
}
  • 当接收到 /hello 请求时,返回纯文本字符串 "Hello SpringBoot!"
  • HTTP 响应头自动包含 Content-Type: text/plain;charset=UTF-8

4)运行项目

回到SpringBootStuDemoApplication中点击Run,编译并运行项目。

修改服务端口:

application.propertiesSpring Boot 应用中主要的配置文件,用于集中管理应用的所有配置设置。它采用简单的键值对格式,是调整 Spring Boot 应用行为的关键方式之一。

位置与加载

  • 默认位置:src/main/resources/application.properties
  • 应用启动时自动加载
  • Spring Boot 按约定优先加载此文件

访问测试:

5)工作流程

  1. 启动应用:Spring Boot 扫描到 @Controller 注解,将 HelloController 注册为 Bean
  2. 接收请求:用户访问 http://localhost:8080/hello
  3. 路由匹配:Spring MVC 根据 @RequestMapping 找到 helloWorldController() 方法
  4. 执行方法:方法返回字符串 "Hello SpringBoot!"
  5. 处理响应@ResponseBody 将返回值直接写入 HTTP 响应体
  6. 返回客户端:浏览器显示纯文本内容 Hello SpringBoot!

6)优化

@RestController  // 组合注解:相当于 @Controller + @ResponseBody
public class HelloController {
    @GetMapping("/hello")  // 明确指定 HTTP GET 方法
    public String hello() {
        return "Hello SpringBoot!";
    }
}
  • **@RestController**:替代 @Controller + @ResponseBody(类中所有方法默认返回响应体)
  • **@GetMapping**:明确限制只响应 GET 请求(更安全规范)

0.3.3 SpringBoot项目的常见目录结构

Spring Boot 项目遵循”约定优于配置”原则,其标准目录结构清晰规范,有利于模块化开发。

project-root/
├── src/
│   ├── main/
│   │   ├── java/                  # Java 源代码目录(核心)
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── app/       # 项目基础包
│   │   │               ├── AppApplication.java  # Spring Boot 主启动类
│   │   │               ├── config/              # 配置类
│   │   │               ├── controller/          # 控制器层
│   │   │               ├── service/             # 服务接口层
│   │   │               ├── service/impl/        # 服务实现层
│   │   │               ├── repository/          # 数据访问层
│   │   │               ├── model/               # 实体类
│   │   │               ├── dto/                 # 数据传输对象
│   │   │               ├── exception/           # 自定义异常
│   │   │               └── util/                # 工具类
│   │   │
│   │   └── resources/             # 资源文件目录(核心)
│   │       ├── static/            # 静态资源(CSS/JS/图片等)
│   │       ├── templates/         # 模板文件(Thymeleaf等)
│   │       ├── application.yml    # 主配置文件(YAML格式)
│   │       ├── banner.txt         # 自定义启动Banner
│   │       ├── db/                # 数据库脚本
│   │       └── ... 
│   │
│   └── test/                     # 测试代码目录
│       ├── java/                 # 测试类(包结构与main对应)
│       └── resources/            # 测试资源文件
│
├── target/                       # 构建输出目录(Maven构建生成)
├── pom.xml                       # Maven配置文件(或build.gradle)
├── .gitignore                    # Git忽略文件配置
└── README.md                     # 项目说明文档
  • **controller**:处理HTTP请求,调用服务层并返回响应。
  • **service**:业务逻辑层接口。
  • **service.impl**:业务逻辑层实现类。
  • repository 或 **dao**:数据访问层(使用Spring Data JPA、MyBatis等)。
  • entity 或 **model**:实体类(与数据库表映射)。
  • **dto**:数据传输对象,用于在层之间传递数据(如请求/响应对象)。
  • **config**:配置类(如安全配置、Web配置、自定义Bean等)。
  • **exception**:自定义异常和全局异常处理器。
  • **util**:工具类(避免放在这里,优先使用静态工具类或依赖注入)。

0.4 SpringBoot Actuator

0.4.1 Actuator简介

Spring Boot Actuator 是 Spring Boot 提供的生产级监控和管理模块,通过暴露一系列 HTTP 或 JMX 端点(Endpoints),帮助开发者实时监控应用状态、收集运行时指标、动态调整配置,并支持与外部监控系统集成。

核心功能与端点:

  • 健康检查(/health

  • 性能指标(/metrics

  • HTTP 请求追踪(/httptrace

  • 动态日志调整(/loggers

  • 环境与配置管理

    • /env:查看所有环境变量和配置属性。
    • /configprops:展示 @ConfigurationProperties 配置集合。
  • 应用基本信息(版本、构建时间)(/info)

  • 导出线程状态(诊断死锁)(/threaddump)

  • 下载 JVM 堆内存快照(/heapdump)

  • 优雅关闭应用(默认禁用)/shutdown

0.4.2 使用方法

1)添加依赖(Maven)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2)暴露端点application.yml

  1. 将 application.properties 改造成 application.yml 格式
  2. 启动 Spring Boot Actuator

创建 application.yml 文件

  1. 删除或重命名原有的 application.properties 文件(建议先备份)
  2. 在相同目录(src/main/resources/)下新建 application.yml 文件

application.yml 文件:

server:
  port: 8889

management:
  endpoints:
    web:
      exposure:
        include: '*'  # 暴露所有端点
  endpoint:
    health:
      show-details: always  # 显示健康详情
    info:
      enabled: true

3)验证配置

  1. 启动应用(运行 SpringBootStuDemoApplication 的 main 方法)
  2. 访问 Actuator 端点:http://localhost:8888/actuator
  3. 查看健康检查:http://localhost:8888/actuator/health

0.5 SpringSecurity

0.5.1 SpringSecurity简介

Spring Security 是 Spring 生态中专为 Java 应用提供安全服务的核心框架,专注于身份认证(Authentication)和授权(Authorization),同时提供全面的攻击防护能力。

1)核心功能

1、身份认证(Authentication)

验证用户身份,支持多种方式:

​ 基础认证:用户名/密码(表单登录、HTTP Basic

​ 第三方认证:OAuth2、LDAP、SAML、JWT 等

​ 社交登录:集成 Google、Facebook 等平台

2、授权(Authorization)

控制用户访问权限,支持:

​ 角色控制(RBAC):基于用户角色(如 ADMIN、USER)限制资源访问

​ 细粒度权限:通过表达式(如 @PreAuthorize(“hasAuthority(‘DELETE’)”) 控制方法级权限

​ 访问控制列表(ACL):针对特定对象(如文件)设置权限

3、安全防护机制

内置防御常见攻击:

​ CSRF 防护:自动验证请求令牌

​ 会话安全:防止会话固定攻击、控制并发会话数

​ 请求头安全:强制 HSTS、X-Content-Type-Options 等

4、扩展性

​ 模块化设计,支持 Web 应用、Reactive 系统、非 Web 服务

​ 可自定义用户存储(数据库、内存、外部服务)

2)工作原理

Spring Security 通过过滤器链(Filter Chain) 拦截请求,核心流程如下:

请求拦截:由 DelegatingFilterProxy 将请求委派给 FilterChainProxy

认证流程:用户提交凭证(如登录表单)→ AuthenticationManager 验证 → 生成 Authentication 对象存储到 SecurityContextHolder。

授权检查:FilterSecurityInterceptor 根据配置的规则(如 URL 或方法注解)验证用户权限。

异常处理:ExceptionTranslationFilter 捕获认证/授权异常,跳转登录页或返回 403 错误。

0.5.2 使用方法

1)依赖配置

Spring Boot添加依赖即自动启用基础安全配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

默认行为:所有端点需认证,生成随机密码(控制台输出),提供 /login 页面。

如图所示,配置完依赖之后,访问之前的actuator端点会重定向到login页面。

访问任何接口(存在/不存在)都会重定向到login页面。

截屏2025-06-27 17.04.13

控制台输出量随机密码,用户名是user,输入即可登录。

  • 自定义用户密码

application.yml:

spring:
  security:
    user:
      name: admin     # 自定义用户名
      password: 123456 # 自定义密码

0.5.3 对比同类框架(Shiro)

0.6 Druid

Druid 是一款高性能的实时分析型数据库(或称为 OLAP 数据库),专为处理大规模数据集的快速查询与分析而设计。它融合了时序数据库、数据仓库和检索系统的核心优势,支持毫秒级实时数据摄入亚秒级查询响应,适用于高并发、高吞吐的交互式分析场景。

参考


文章作者: 司晓凯
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 司晓凯 !
  目录