SpringSecurity原理解析(五):HttpSecurity 类处理流程
1、SpringSecurity 在spring boot中与SSM项目中基于配置文件的区别
通过前边的笔记我们可以知道,在传统的SSM项目中 SpringSecurity的使用是基于配置文件
的,然后spring 容器初始化的时候将 SpringSecurity 中的各种标签解析成对应的Bean对象,
SpringSecurity 配置文件如下所示:
<!-- SpringSecurity配置文件 --><!--auto-config:表示自动加载SpringSecurity的配置文件use-expressions:表示使用Spring的EL表达式--><security:http auto-config="true" use-expressions="true"><!--定义匿名访问,跳转到登录页面 --><security:intercept-url pattern="/login.jsp" access="permitAll()"/><!--拦截资源pattern="/**" 拦截所有的资源access="hasAnyRole('ROLE_USER')" 表示只有ROLE_USER 这个角色可以访问资源--><security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER')" ></security:intercept-url><!--配置认证(用户登录)信息,覆盖security 默认的登录页面login-page:登录页面地址login-processing-url:登录的请求urldefault-target-url:登录成功皇后的目标地址authentication-failure-url:登录校验失败后的地址--><security:form-login login-page="/login.jsp" login-processing-url="/login" default-target-url="/home.jsp" authentication-failure-url="/error.jsp"/><!--开启csrf校验 --><security:csrf disabled="true"/><!--开启“记住我” 登录用户缓存功能,该功能默认是关闭的,需要手动开启remember-me-parameter 是登录页面配置的 “记住我” 功能的属性名称,如login.jsp 中的 "remember-me"token-validity-seconds 设置 “记住我” 登录的数据保存的超时时间,注意:当前 这种配置只是把“登录数据” 临时保存在页面的Cookie(token) 中,保存在页面中的数据安全性很差,很容故意被盗取;为了解决这个问题 spring security提供了把“记住我” 功能的数据保存到数据库中,需要在 <security:remember-me>中添加配置属性 data-source-ref,并 指定数据源,如:data-source-ref="dataSource"--><security:remember-metoken-validity-seconds="1200"data-source-ref="dataSource"remember-me-parameter="remember-me"/><!--自定义错误页面 --><security:access-denied-handler error-page="error.jsp"/></security:http><!--向IOC容器注入一个bean--><bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="bCryptPasswordEncoder"/><!-- 认证用户信息 --><security:authentication-manager><security:authentication-provider user-service-ref="userServiceImpl"><!--指向自己定义的认证service,在service 中根据登录用户与数据库的数据进行用户认证处理,这样保密性比较好 --><!--<security:user-service >设置一个账号 zhangsan 密码123 {noop} 表示不加密 具有的角色是 ROLE_USER<security:user name="zhangsan" authorities="ROLE_USER" password="{noop}123" ></security:user><security:user name="lisi" authorities="ROLE_USER" password="{noop}123456" ></security:user></security:user-service>--><!--引入用户认证密码加密方式 --><security:password-encoder ref="bCryptPasswordEncoder"></security:password-encoder></security:authentication-provider></security:authentication-manager>
也就是在配置文件中通过 security:http 等标签来定义了认证需要的相关信息,但是在
SpringBoot项目中,我们慢慢脱离了xml配置文件的方式,通过配置类的方式来配置
SpringSecurity。SpringSecurity配置类需要继承类 WebSecurityConfigurerAdapter,并重写
configure(AuthenticationManagerBuilder auth) 和 configure(HttpSecurity http) 方法;
SpringSecurity 配置类如下所示:
/*** SpringSecurity的配置文件* WebSecurityCofniguration中 @Bean注解 把 FilterChainProxy 注入到了容器中 而且名称为springSecurityFilterChain* 而 FilterChainProxy 对象是通过 WebSecurity 构建的** @EnableWebSecurity*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowiredprivate UserService userService;@Autowiredprivate BCryptPasswordEncoder bCryptPasswordEncoder;@Autowiredprivate PersistentTokenRepository persistentTokenRepository;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService)// 数据库认证,绑定需要执行用户认证操作的service.passwordEncoder(bCryptPasswordEncoder); // 设置加密处理的方式//auth.inMemoryAuthentication().withUser("root").password("123")}/*** 容器中注入 BCryptPasswordEncoder* @return*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder(){return new BCryptPasswordEncoder();}/*** HttpSecurity 相当于 SpringSecurity配置文件中 http 标签** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//匿名访问资源.antMatchers("/login.html","/css/**","/img/**")// 配置需要放过的资源,表示前边 antMatchers 配置的资源都需要放过.permitAll().antMatchers("/**")//认证的资源及所具备的权限.hasAnyRole("USER").anyRequest()//表示所有请求都需要认证.authenticated()//需要认证//and() 返回一个HttpSecurity.and()// 配置登录表单相关的信息.formLogin()// 指定自定义的登录页面//todo 注意:// 对于前后端分离的项目,不需要指定跳转的页面,只需要 loginProcessingUrl// 设置请求资源url就行了.loginPage("/login.html") //认证表单相关信息.loginProcessingUrl("/login") // 表单提交的登录地址.defaultSuccessUrl("/home.html")//表示上边与form表单提交得资源都要放过.permitAll().and().rememberMe() // 放开 记住我 的功能.tokenRepository(persistentTokenRepository) // 持久化.and()//csrf设置.csrf().disable();HttpSecurity http1 = http.authorizeRequests()// 配置需要放过的资源.antMatchers("/login.html", "/css/**", "/img/**").permitAll()//表示放过前边 antMatchers 配置得资源.antMatchers("/**").hasAnyRole("USER").anyRequest().authenticated().and();}/*** 向Spring容器中注入 PersistentTokenRepository 对象* @param dataSource* @return*/@Beanpublic PersistentTokenRepository persistentTokenRepository(DataSource dataSource){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();//绑定数据源tokenRepository.setDataSource(dataSource);return tokenRepository;}public static void main(String[] args) {BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String password = "admin";// 每次都会生成一个随机的salt,同一个明文加密多次编码得到的密文其实都不一样System.out.println(encoder.encode(password));System.out.println(encoder.encode(password));System.out.println(encoder.encode(password));}
}
在SpringSecurity中提供了HttpSecurity等工具类,这里HttpSecurity就等同于我们在配置
文件中定义的<security:http>标签,而。
通过代码结果来看和配置文件的效果是一样的。基于配置文件的方式我们之前分析过,是通过
标签对应的handler来解析处理的,那么HttpSecurity这块是如何处理的呢?
2、HttpSecurity 类的处理过程
2.1、HttpSecurity 类图:

由该类图可以清晰得发现,HttpSecurity 继承了父类 AbstractConfiguredSecurityBuilder
并实现了接口 SecurityBuilder 和 HttpSecurityBuilder
HttpSecurity 类的定义如下:
2.2、SecurityBuilder 接口
SecurityBuilder 定义如下:
public interface SecurityBuilder<O> {//构建 SecurityBuilder 指定泛型类型的对象O build() throws Exception;
}
由接口 SecurityBuilder 的定义可以发现,SecurityBuilder 接口只提供了一个 build() 方法,用
来构建 SecurityBuilder 泛型指定类型的bean对象。
结合 HttpSecurity 类中实现 SecurityBuilder 接口时的泛型是什么,就知道在 HttpSecurity 类
中 SecurityBuilder 是用来创建什么对象,HttpSecurity 定义如下:

由 HttpSecurity 的定义可以发现,在 HttpSecurity 类中 SecurityBuilder 指定的泛型是
DefaultSecurityFilterChain,DefaultSecurityFilterChain 是拦截器链SecurityFilterChain
一个默认实现,所以 DefaultSecurityFilterChain 是一个拦截器链,所以在 HttpSecurity
中,SecurityBuilder 是用来创建拦截器链的。
2.2.1、SecurityBuilder.build() 方法的实现
下面看下 SecurityBuilder.build() 的实现过程,及连接器链的创建过程
SecurityBuilder 的默认实现是类 AbstractSecurityBuilder
SecurityBuilder.build() 方法的实现如下:
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {//CAS类型private AtomicBoolean building = new AtomicBoolean();//返回创建的O的对象private O object;public AbstractSecurityBuilder() {}//创建泛型O的对象public final O build() throws Exception {//基于CAS,保证在整个环境中O只被创建一次if (this.building.compareAndSet(false, true)) {//真正创建泛型O的对象this.object = this.doBuild();return this.object;} else {throw new AlreadyBuiltException("This object has already been built");}}//返回O的对象public final O getObject() {if (!this.building.get()) {throw new IllegalStateException("This object has not been built");} else {return this.object;}}//抽象方法,由子类实现protected abstract O doBuild() throws Exception;
}
由 AbstractSecurityBuilder 的定义可以发现,真正创建泛型O(在 HttpSecurity 中O是
拦截器链 DefaultSecurityFilterChain )的对象是在doBuild 发给发中完成,而doBuild是
一个抽象方法,由子类 AbstractConfiguredSecurityBuilder 实现,
doBuild 方法实现如下:
protected final O doBuild() throws Exception {synchronized(this.configurers) {this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;this.beforeInit();//执行当前类的init方法进行初始化操作this.init();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;this.beforeConfigure();this.configure();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;//获取构建的对象,上面的方法可以先忽略O result = this.performBuild();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;return result;}}
performBuild() 是一个抽象方法,由AuthenticationManagerBuilder、HttpSecurity、
WebSecurity 三个子类实现,在这里我们应该看 HttpSecurity 中的实现
HttpSecurity.performBuild() 方法的实现如下:
@Overrideprotected DefaultSecurityFilterChain performBuild() {//filters:保存所有的过滤器// 对所有的过滤器做排序this.filters.sort(OrderComparator.INSTANCE);List<Filter> sortedFilters = new ArrayList<>(this.filters.size());for (Filter filter : this.filters) {sortedFilters.add(((OrderedFilter) filter).filter);}// 然后生成 DefaultSecurityFilterChainreturn new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);}
DefaultSecurityFilterChain 构造方法如下:
public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {if (!filters.isEmpty()) {logger.info(LogMessage.format("Will not secure %s", requestMatcher));} else {logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters));}//绑定请求匹配规则this.requestMatcher = requestMatcher;//绑定过滤器集合this.filters = new ArrayList(filters);}
在HttpSecurity构造方法中绑定了对应的请求匹配器和过滤器集合。

对应的请求匹配器则是 AnyRequestMatcher 匹配所有的请求。当然我们会比较关心
默认的过滤器链中的过滤器是哪来的,这块儿我们继续来分析
2.3、AbstractConfiguredSecurityBuilder
AbstractConfiguredSecurityBuilder 是一个抽象类,也可以看成是 SecurityBuilder 接口的
实现,AbstractConfiguredSecurityBuilder 类图如下所示:

| 类型 | 功能 |
| SecurityBuilder | 声明了build方法 |
| AbstractSecurityBuilder | 提供了获取对象的方法以及控制一个对象只能build一次 |
| AbstractConfiguredSecurityBuilder | 除了提供对对象细粒度的控制外还扩展了对configurer的操作 |
AbstractConfiguredSecurityBuilder 对应的三个实现类,如下所示:

2.3.1、BuildState
AbstractConfiguredSecurityBuilder 中定义了一个枚举类BuildState,将整个构建过程
分为 5 种状态,也可 以理解为构建过程生命周期的五个阶段,通过这些阶段来管理需
要构建的对象的不同阶段 如下:
private enum BuildState {/*** 还没开始构建*/UNBUILT(0),/*** 构建中*/INITIALIZING(1),/*** 配置中*/CONFIGURING(2),/*** 构建中*/BUILDING(3),/*** 构建完成*/BUILT(4);private final int order;BuildState(int order) {this.order = order;}public boolean isInitializing() {return INITIALIZING.order == this.order;}/*** Determines if the state is CONFIGURING or later* @return*/public boolean isConfigured() {return this.order >= CONFIGURING.order;}}
2.3.2、AbstractConfiguredSecurityBuilder 常见方法
2.3.2.1、add() 方法
add 方法,这相当于是在收集所有的配置类。将所有的 xxxConfigure 收集起来存储到
configurers 中,将来再统一初始化并配置,configurers 本身是一个 LinkedHashMap ,
key 是配置类的 class, value 是一个集合,集合里边放着 xxxConfigure 配置类。当
需要对这些配置类进行集中配置的时候, 会通过 getConfigurers 方法获取配置类,
这个获取过程就是把 LinkedHashMap 中的 value 拿出来, 放到一个集合中返回。
add 方法代码如下:
private <C extends SecurityConfigurer<O, B>> void add(C configurer) {Assert.notNull(configurer, "configurer cannot be null");//configurer必须是 SecurityConfigurer 的子类Class<? extends SecurityConfigurer<O, B>> clazz = configurer.getClass();synchronized(this.configurers) {if (this.buildState.isConfigured()) {throw new IllegalStateException("Cannot apply " + configurer + " to already built object");} else {List<SecurityConfigurer<O, B>> configs = null;if (this.allowConfigurersOfSameType) {configs = (List)this.configurers.get(clazz);}List<SecurityConfigurer<O, B>> configs = configs != null ? configs : new ArrayList(1);((List)configs).add(configurer);this.configurers.put(clazz, configs);if (this.buildState.isInitializing()) {this.configurersAddedInInitializing.add(configurer);}}}}//获取指定的配置类
@SuppressWarnings("unchecked")public <C extends SecurityConfigurer<O, B>> List<C> getConfigurers(Class<C> clazz) {List<C> configs = (List<C>) this.configurers.get(clazz);if (configs == null) {return new ArrayList<>();}return new ArrayList<>(configs);}
2.3.2.2、doBuild()方法
@Overrideprotected final O doBuild() throws Exception {synchronized (this.configurers) {this.buildState = BuildState.INITIALIZING;beforeInit(); //是一个预留方法,没有任何实现init(); // 就是找到所有的 xxxConfigure,挨个调用其 init 方法进行初始化,完成默认过滤器的初始化this.buildState = BuildState.CONFIGURING;beforeConfigure(); // 是一个预留方法,没有任何实现configure(); // 就是找到所有的 xxxConfigure,挨个调用其 configure 方法进行配置。this.buildState = BuildState.BUILDING;O result = performBuild();
// 是真正的过滤器链构建方法,但是在 AbstractConfiguredSecurityBuilder中 performBuild 方法只是一个抽象方法,具体的实现在 HttpSecurity 中this.buildState = BuildState.BUILT;return result;}}
init方法:完成所有相关过滤器的初始化
private void init() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();for (SecurityConfigurer<O, B> configurer : configurers) {configurer.init((B) this); // 初始化对应的过滤器}for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {configurer.init((B) this);}}
configure方法:完成HttpSecurity和对应的过滤器的绑定。
private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();for (SecurityConfigurer<O, B> configurer : configurers) {configurer.configure((B) this);}}
2.4、HttpSecurity
HttpSecurity 做的事情,就是对各种各样的 xxxConfigurer 进行配置;
HttpSecurity 部分方法列表如下:

HttpSecurity 中有大量类似的方法,过滤器链中的过滤器就是这样一个一个配置的。我们
就不一一介绍 了。每个配置方法的结尾都会调用一次 getOrApply 方法,getOrApply
方法是做什么的?
getOrApply 方法如下:
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(C configurer)throws Exception {C existingConfig = (C) getConfigurer(configurer.getClass());if (existingConfig != null) {return existingConfig;}return apply(configurer);}
getConfigurer 方法是在它的父类 AbstractConfiguredSecurityBuilder 中定义的,目的就
是去查看当前 这个 xxxConfigurer 是否已经配置过了。
如果当前 xxxConfigurer 已经配置过了,则直接返回,否则调用 apply 方法,这个 apply
方法最终会调 用到 AbstractConfiguredSecurityBuilder#add 方法,将当前配置
configurer 收集起来 HttpSecurity 中还有一个 addFilter 方法.
addFilter 方法如下所示:
@Overridepublic HttpSecurity addFilter(Filter filter) {Integer order = this.filterOrders.getOrder(filter.getClass());if (order == null) {throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()+ " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");}this.filters.add(new OrderedFilter(filter, order));return this;}
这个 addFilter 方法的作用,主要是在各个 xxxConfigurer 进行配置的时候,会调用到这
个方法, (xxxConfigurer 就是用来配置过滤器的),把 Filter 都添加到 fitlers 变量中。
3、总结
这就是 HttpSecurity 的一个大致工作流程。把握住了这个工作流程,剩下的就只是一些简
单的重 复的 xxxConfigurer 配置了
相关文章:
SpringSecurity原理解析(五):HttpSecurity 类处理流程
1、SpringSecurity 在spring boot中与SSM项目中基于配置文件的区别 通过前边的笔记我们可以知道,在传统的SSM项目中 SpringSecurity的使用是基于配置文件 的,然后spring 容器初始化的时候将 SpringSecurity 中的各种标签解析成对应的Bean对象,…...
C++系列-匿名对象
匿名对象 💢什么是匿名对象💢匿名对象的创建方式及作用域💢匿名对象的对象类型💢💢匿名的基本数据类型对象💢💢匿名的自定义的类类型对象💢💢匿名的标准库的类对象 &…...
tofixed和math.round什么区别
1、floor 返回不大于的最大整数(向下取整) 2、round 则是4舍5入的计算,入的时候是到大于它的整数(当-1.5时可见,四舍五入后得到的结果不是我们期待的,解决办法是先对他取绝对值,然后在用round方…...
OPENAIGC开发者大赛高校组金奖 | 基于混合大语言模型与多模态的全过程通用AI Agent
在第二届拯救者杯OPENAIGC开发者大赛中,涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到,我们特意开设了优秀作品报道专栏,旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者,希望能带给您…...
MySql批量迁移数据库
导出数据库 将指定数据库实例(MYSQL_HOST、MYSQL_PORT、MYSQL_USER、MYSQL_PASSWORD)中的所有数据库(表结构、数据)导出到指定目录(BACKUP_DIR)下的多个单独的SQL脚本,每个SQL脚本名称即为数据…...
一、selenium自动化简介selenium工具集
文章目录 一、简介二、组成部分三、selenium工具集3.1 Selenium IDE3.2 Selenium WebDriver3.3 Selenium Grid3.4 Appium 一、简介 官方网站 Selenium 是支持 web 浏览器自动化的一系列工具和库的综合项目。 它提供了扩展来模拟用户与浏览器的交互,用于扩展浏览器分…...
CCF推荐B类会议和期刊总结:(计算机网络领域)
CCF推荐B类会议和期刊总结(计算机网络领域) 在计算机网络领域,中国计算机学会(CCF)推荐的B类会议和期刊代表了该领域的较高水平。以下是对所有B类会议和期刊的总结,包括全称、出版社、dblp文献网址以及所属…...
[Web安全 网络安全]-文件包含漏洞
文章目录: 一:前言 1.什么是文件包含漏洞 2.文件包含漏洞的成因 3.文件包含漏洞的分类 4.文件包含漏洞的防御策略 5.文件包含函数(触发点Sink) 6.环境 6.1 靶场 6.2 其他工具 二:文件包含LFI labs靶场实验…...
使用soui4实现一个拾色器
拾色器类 #pragma once class CClrPickerCtrl : public SWindow {DEF_SOBJECT(SWindow, L"clrpicker") public:CClrPickerCtrl(void);~CClrPickerCtrl(void);//跟solider控件设置色调void SetSliderPos(int nPos);//获取选取位置的颜色COLORREF GetColor(); protect…...
Thinkphp5 + Swoole实现邮箱异步通知
在 ThinkPHP 中实现邮箱异步通知的常见做法是通过队列系统来处理异步任务,结合 Swoole 来处理异步发送邮件的请求。这样可以避免同步处理邮件发送导致的阻塞,提高响应速度。 以下是基于 ThinkPHP5 框架和 Swoole 的异步邮件通知实现步骤: 一…...
LLM - 理解 多模态大语言模型 (MLLM) 的预训练与相关技术 (三)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/142063880 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 完备(F…...
工具篇之Joda-Time
在Java应用程序开发中,处理日期和时间是一项常见且复杂的任务。尽管Java标准库提供了基本的日期和时间操作类,但它们的使用常常不够直观和灵活。Joda-Time 是一个强大的日期和时间库,提供了丰富的API,用于简化日期和时间的操作。本…...
架构师应该懂得东西,软考应该具备的
架构师应该懂得知识 架构师作为软件系统设计和开发的关键角色,需要掌握广泛的知识和技能。具体来说,他们应该懂得以下几方面的知识: 编程语言:掌握至少一种编程语言,如Java、C、Python等,以便于进行系统设…...
图论篇--代码随想录算法训练营第五十一天打卡| 99. 岛屿数量(深搜版),99. 岛屿数量(广搜版),100. 岛屿的最大面积
99. 岛屿数量(深搜版) 题目链接:99. 岛屿数量 题目描述: 给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而…...
什么是API网关(API Gateway)?
1. 什么是API网关(API Gateway)? 在微服务体系结构中,客户端可能与多个前端服务进行交互。 API 网关位于客户端与服务之间。 它充当反向代理,将来自客户端的请求路由到服务。 它还可以执行各种横切任务,例…...
对话:LLC磁集成能否成为充电桩模块电源常态产品?
编者按:在终端需求疲软的影响下,前两年火热的新能源汽车、光伏、储能等新能源领域也掀起了价格战,储能已正式进入0.5元时代,新能源汽车领域价格战更是一轮接一轮,成本管控成为2024年企业绕不开的话题。 接下来我们将围…...
基于SSM的二手物品交易管理系统的设计与实现 (含源码+sql+视频导入教程+文档+PPT)
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的二手物品交易管理系统7拥有两种角色 管理员:用户管理、分类管理、商品管理、订单管理、系统管理等 用户:登录注册、充值、收货、评价、收藏、购物车、订…...
视觉语言模型中的人脸社会感知
本文研究了视觉语言模型CLIP在处理人脸图像时的社会感知能力及其潜在偏见。研究者们构建了一个名为CausalFace的合成人脸数据集,通过系统地独立变化年龄、性别、人种、面部表情、照明和姿势等六个维度来评估模型的社会感知。他们发现,尽管CLIP是在多样化…...
JAVA学习-练习试用Java实现“最小覆盖子串”
问题: 给定一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。 注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。 示例 1&…...
关于axios同步获取数据的问题
axios同步获取数据 Axios介绍问题代码修改 总结 Axios介绍 Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 X…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
