当前位置: 首页 > news >正文

第一章 初识 Spring Security

第一章 初识 Spring Security

1、权限管理

权限管理

  • 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现了对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源
  • 权限管理包括用户身份认证授权两部分,简称认证授权。对于访问控制的资源用户首先需要经过身份认证,认证通过后用户具有该资源的访问权限方可访问。

认证

身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则出示指纹;对于硬件Key等刷卡系统,则需要刷卡。

授权

授权,即访问控制,控制谁能访问哪些资源。用户进行身份认证后需要分配权限方可访问系统的资源,对于某些资源如果没有权限那么该用户是无法访问的。

行业解决方案

和其他领域不同,在 Java 企业级开发中,安全管理框架非常少,目前比较常见的就是:

  1. Shiro

Shiro 本身是一个老牌的安全管理框架,有着众多的优点,例如轻量、简单、易于集成、可以在 JavaSE 环境中使用等。不过,在微服务时代,Shiro 就显得力不从心了,它在微服务面前和扩展方面,无法充分展示自己的优势。

  1. 开发者自定义

也有很多公司选择自定义权限,即自己开发权限管理。但是一个系统的安全,不仅仅是登录和权限控制这么简单,我们还要考虑各种各样可能存在的网络政击以及防御策略,从这个角度来说,开发者自己实现安全管理也并非是一件容易的事情,只有大公司才有足够的人力物力去支持这件事情。

  1. Spring Security

Spring Security,作为 Spring 家族的一员,在和 Spring 家族的其他成员如 Spring Boot、Spring Clond 等进行整合时,具有其他框架无可比拟的优势,同时对 OAuth2 有着良好的支持,再加上 Spring Cloud 对 Spring Security 的不断加持(如推出 Spring Cloud Security ),让 Spring Securiy 不知不觉中成为微服务项目的首选安全管理方案。

简介

官方定义

  • https://spring.io/projects/spring-security

Spring Security 是一个功能强大、可高度定制的身份验证和访问控制的框架。它是保护基于 Spring 应用程序的事实标准。

Spring Security 是一个面向 Java 应用程序提供身份验证和安全性的框架。与所有 Spring 项目一样,Spring Security 的真正威力在于它可以轻松地扩展以满足定制需求。

历史

Spring Security 最早叫 Acegi Security, 这个名称并不是说它和 Spring 就没有关系,它依然是为 Spring 框架提供安全支持的。Acegi Security 基于 Spring,可以帮助我们为项目建立丰富的角色与权限管理系统。Acegi Security 虽然好用,但是最为让人诟病的则是它臃肿繁琐的配置这一问题最终也遗传给了 Spring Security。

Acegi Security 最终被并入 Spring Security 项目中,并于 2008 年4月发布了改名后的第一个版本 Spring Security 2.0.0,到目前为止,Spring Security 的最新版本己经到了 5.6.1。和 Shiro 相比,Spring Security 重量级并且配置繁琐,直至今天,依然有人以此为理由而拒绝了解 Spring Security。其实,自从 Spring Boot 推出后,就彻底颠覆了传统了 JavaEE 开发,自动化配置让许多事情变得非常容易,包括 Spring Security 的配置。在一个 Spring Boot 项目中,我们甚至只需要引入一个依赖,不需要任何额外配置,项目中的所有接口就会被自动保护起来了。在 Spring Cloud中,很多涉及安全管理的问题,也是一个 Spring Security 依赖两行配置就能搞定,在和 Spring 家族的产品一起使用时,Spring Security 的优势就非常明显了。

因此,在微服务时代,我们不需要纠结要不要学习 Spring Security,我们要考虑的是如何快速掌握 Spring Security, 并且能够使用 Spring Security 实现我们微服务的安全管理。

整体架构

在 Spring Security 的架构设计中,认证授权 是分开的,无论使用什么样的认证方式。都不会影响授权,这是两个独立的存在,这种独立带来的好处之一,就是可以非常方便地整合一些外部的解决方案。

Untitled

认证

1、AuthenticationManager

在 Spring Security 中认证是由 AuthenticationManager 接口来负责的,接口定义为:

Untitled

public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
  • 返回 Authentication 表示认证成功
  • 返回 AuthenticationException 异常,表示认证失败。

AuthenticationManager 主要实现类为 ProviderManager,在 ProviderManager 中管理了众多 AuthenticationProvider 实例。在一次完整的认证流程中,Spring Security 允许存在多个 AuthenticationProvider ,用来实现多种认证方式,这些 AuthenticationProvider 都是由 ProviderManager 进行统一管理的。

Untitled

2、Authentication

认证以及认证成功的信息主要是由 Authentication 的实现类进行保存的,其接口定义为:

Untitled

public interface Authentication extends Principal, Serializable {Collection<? extends GrantedAuthority> getAuthorities();Object getCredentials();Object getDetails();Object getPrincipal();boolean isAuthenticated();void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
  • getAuthorities:获取用户权限信息
  • getCredentials:获取用户凭证信息,一般指密码
  • getDetails:获取用户详细信息
  • getPrincipal:获取用户身份信息,用户名、用户对象等
  • isAuthenticated:用户是否认证成功

3、SecurityContextHolder

SecurityContextHolder 用来获取登录之后的用户信息。Spring Security 会将登录用户数据保存在 Session 中。但是为了使用方便,Spring Security 在此基础上还做了一些改进,其中最主要的一个变化就是线程绑定。当用户登录成功之后,Spring Security 会将登录成功的用户信息保存到 SecurityContextHolder 中。

SecurityContextHolder 中的数据保存默认是通过 ThreadLocal 来实现的,使用 ThreadLocal 创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是将用户数据和请求线程绑定在一起。当登录请求处理完毕后,Spring Security 会将 SecurityContextHolder 中的数据拿出来保存到 Session 中,同时将 SecurityContexHolder 中的数据清空。以后每当有请求到来时,Spring Security 就会先从 Session 中取出用户登录数据,保存到 SecurityContextHolder 中,方便在该请求的后续处理过程中使用,同时在请求结束时将 SecurityContextHolder 中的数据拿出来保存到 Session 中,然后将 Security SecurityContextHolder 中的数据清空。这一策略非常方便用户在 Controller、Service 层以及任何代码中获取当前登录用户数据。

Untitled

授权

当完成认证后,接下来就是授权了。在 Spring Security 的授权体系中,有两个关键接口:

1、AccessDecisionManager

AccessDecisionManager(访问决策管理器),用来决定此次访问是否被允许。

Untitled

2、AccessDecisionVoter

AccessDecisionVoter(访问决定投票器),投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。

Untitled

AccessDecisionVoter 和 AccessDecisionManager 都有众多的实现类,在 AccessDecisionManager 中会挨个遍历 AccessDecisionVoter,进而决定是否允许用户访问,因而 AccessDecisionVoter 和 AccessDecisionManager 两者的关系类似于 AuthenticationProvider 和 ProviderManager 的关系。

3、ConfigAttribute

ConfigAttribute,用来保存授权时的角色信息。

Untitled

在 Spring Security 中,用户请求一个资源(通常是一个接口或者是一个 Java 方法)需要的角色会被封装成一个 ConfigAttribute 对象,在 ConfigAttribute 中只有一个 getAttribute 方法,该方法返回一个 String 字符串,就是角色的名称。一般来说,角色名称都带有一个 ROLE_ 前缀,投票器 AccessDecisionVoter 所做的事情,其实就是比较用户所具备的角色和请求某个资源所需要的 ConfigAttribute 之间的关系。

2、环境搭建

  • Spring Boot
  • Spring Security
    • 认证:判断用户是否是系统合法用户的过程
    • 授权:判断系统内的用户可以访问或具有访问哪些资源的权限的过程

整合 Spring Security

1、创建 Spring Boot 应用

Untitled

2、引入 Spring Security 相关依赖

<!--引入spring security依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

3、创建 Controller

@RestController
public class HelloController {@RequestMapping("/hello")public String hello() {System.out.println("hello security");return "hello spring security";}}

4、启动项目

  • 启动完成后在控制台会生成一个密码
  • 访问 /hello 发现直接跳转到登录页面

Untitled

Untitled

5、登录系统

- 默认用户名为: user
- 默认密码为:  控制台打印的uuid

Untitled

Untitled

这就是 Spring Security 的强大之处,只需要引入一个依赖,所有的接口就会被自动保护起来!

思考🤔?

  • 为什么引入 Spring Security 之后没有任何配置所有请求就要认证呢?
  • 在项目中明明没有登录界面,登录界面怎么来的呢?
  • 为什么使用 user控制台密码 就能完成登陆,登录时验证数据源存在哪里呢?

实现原理

https://docs.spring.io/spring-security/site/docs/5.5.4/reference/html5/#servlet-architecture

虽然开发者只需要引入一个依赖,就可以让 Spring Security 对应用进行保护。那么 Spring Security 又是如何做到的呢?

在 Spring Security 中 认证、授权 等功能都是基于过滤器完成的。

Untitled

Untitled

需要注意的是,默认过滤器并不是直接放在 Web 项目的原生过滤器链中,而是通过一个 FlterChainProxy 来统一管理。Spring Security 中的过滤器链通过 FilterChainProxy 嵌入到 Web 项目的原生过滤器链中。FilterChainProxy 作为一个顶层的管理者,将统一管理 Security Filter。FilterChainProxy 本身是通过 Spring 框架提供的 DelegatingFilterProxy 整合到原生的过滤器链中。

Security Filters

那么在 Spring Security 中默认给我们提供了哪些过滤器呢 ? 哪些过滤器会被加载呢 ?

以下是 Spring Security Filter 排序的完整列表:

过滤器过滤器作用默认是否加载
ChannelProcessingFilter过滤请求协议 HTTP 、HTTPSNO
WebAsyncManagerIntegrationFilter将 WebAsyncManger 与 SpringSecurity 上下文进行集成YES
SecurityContextPersistenceFilter在处理请求之前,将安全信息加载到 SecurityContextHolder 中YES
HeaderWriterFilter处理头信息加入到响应中YES
CorsFilter处理跨域问题NO
CsrfFilter处理 CSRF 攻击YES
LogoutFilter处理注销登录YES
OAuth2AuthorizationRequestRedirectFilter处理 OAuth2 认证重定向NO
Saml2WebSsoAuthenticationRequestFilter处理 SAML 认证NO
X509AuthenticationFilter处理 X509 认证NO
AbstractPreAuthenticatedProcessingFilter处理预认证问题NO
CasAuthenticationFilter处理 CAS 单点登录NO
OAuth2LoginAuthenticationFilter处理 OAuth2 认证NO
Saml2WebSsoAuthenticationFilter处理 SAML 认证NO
UsernamePasswordAuthenticationFilter处理表单登录YES
OpenIDAuthenticationFilter处理 OpenID 认证NO
DefaultLoginPageGeneratingFilter配置默认登录页面YES
DefaultLogoutPageGeneratingFilter配置默认注销页面YES
ConcurrentSessionFilter处理 Session 有效期NO
DigestAuthenticationFilter处理 HTTP 摘要认证NO
BearerTokenAuthenticationFilter处理 OAuth2 认证的 Access TokenNO
BasicAuthenticationFilter处理 HttpBasic 登录YES
RequestCacheAwareFilter处理请求缓存YES
SecurityContextHolder
AwareRequestFilter
包装原始请求YES
JaasApiIntegrationFilter处理 JAAS 认证NO
RememberMeAuthenticationFilter处理 RememberMe 登录NO
AnonymousAuthenticationFilter配置匿名认证YES
OAuth2AuthorizationCodeGrantFilter处理OAuth2认证中授权码NO
SessionManagementFilter处理 session 并发问题YES
ExceptionTranslationFilter处理认证/授权中的异常YES
FilterSecurityInterceptor处理授权相关YES
SwitchUserFilter处理账户切换NO

可以看出,Spring Security 提供了 30 多个过滤器。默认情况下 Spring Boot 在对 Spring Security 进入自动化配置时,会创建一个名为 SpringSecurityFilerChain 的过滤器,并注入到 Spring 容器中,这个过滤器将负责所有的安全管理,包括用户认证、授权、重定向到登录页面等。具体可以参考 WebSecurityConfiguration 的源码:

Untitled

Untitled

Untitled

SpringBootWebSecurityConfiguration

这个类是 Spring Boot 的自动配置类,通过这个源码得知,默认情况下对所有请求进行权限控制:

Untitled

Untitled

@Configuration(proxyBeanMethods = false)
// 什么时候使用默认的Spring Security呢?点击这个类看看
@ConditionalOnDefaultWebSecurity
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {@Bean@Order(SecurityProperties.BASIC_AUTH_ORDER)// HttpSecurity:这里先当做Http请求SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {// 默认对所有的Http请求都需要认证之后才能进行访问http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();return http.build();}}

这也就是为什么在引入 Spring Security 中没有任何配置得情况下,请求会被拦截的原因!

通过上面对自动配置的分析,我们也能看出默认生效的条件为:

Untitled

  • 条件一:ClassPath 中存在 SecurityFilterChain.class、HttpSecurity.class
  • 条件二:在 Spring 容器中没有找到 WebSecurityConfigurerAdapter.class、SecurityFilterChain.class 对应的 Bean 对象
    • 修改配置,用 WebSecurityConfigurerAdapter
    • 扩展 Filter,用 SecurityFilterChain

默认情况下,这两个条件都是满足的。WebSecurityConfigurerAdapter 这个类极其重要,Spring Security 的核心配置都在这个类中:

Untitled

Untitled

如果要对 Spring Security 进行自定义配置,就要自定义这个类实例,通过覆盖类中的方法以达到修改默认配置的目的。

流程分析

Untitled

1、请求 /hello 接口,在引入 Spring Security 之后会先经过一些过滤器。

2、在请求到达 FilterSecurityInterceptor时,发现请求并未认证。请求拦截下来,并抛出 AccessDeniedException 异常。

3、抛出 AccessDeniedException 的异常会被 ExceptionTranslationFilter 捕获,这个 Filter 中会调用 LoginUrlAuthenticationEntryPoint#commence 方法给客户端返回 302,要求客户端进行重定向到 /login 页面。

4、客户端发送 /login 请求。

5、/login 请求会再次被拦截器中的 DefaultLoginPageGeneratingFilter 拦截到,并在拦截器中返回生成的登录页面。

Untitled

Untitled

通过这种方式,Spring Security 默认过滤器中生成了登录页面,并返回!

默认用户生成

1、查看 SpringBootWebSecurityConfiguration#defaultSecurityFilterChain 方法进行表单登录

Untitled

2、处理登录为 FormLoginConfigurer 类,在里面调用了 UsernamePasswordAuthenticationFilter 这个类实例

Untitled

3、查看类中的 UsernamePasswordAuthenticationFilter#attempAuthentication 方法,得知实际调用的是 AuthenticationManager 类中的 authenticate 方法

Untitled

4、调用 ProviderManager 类中的 authenticate 方法

Untitled

5、调用了 ProviderManager 的实现类 AbstractUserDetailsAuthenticationProvider 类中的 authenticate 方法

Untitled

6、最终调用实现类 DaoAuthenticationProvider 中的方法作比较

Untitled

Untitled

看到这里就能发现默认是基于 InMemoryUserDetailsManager 这个类实现的,也就是基于内存的实现!

UserDetailService

通过源码分析也能得知 UserDetailService 是顶层父接口,接口中的 loadUserByUserName 方法是用来在认证时进行用户名认证的,默认是基于内存实现的;如果想要修改成基于数据库实现我们只需要自定义 UserDetailService 实现类,最终返回 UserDetails 实例即可。

Untitled

Untitled

UserDetailsServiceAutoConfiguration

这个源码非常多,这里梳理了关键部分:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(AuthenticationManager.class)
@ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean(value = { AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class,AuthenticationManagerResolver.class },type = { "org.springframework.security.oauth2.jwt.JwtDecoder","org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector","org.springframework.security.oauth2.client.registration.ClientRegistrationRepository" })
public class UserDetailsServiceAutoConfiguration {//....@Bean@Lazypublic InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties,ObjectProvider<PasswordEncoder> passwordEncoder) {SecurityProperties.User user = properties.getUser();List<String> roles = user.getRoles();return new InMemoryUserDetailsManager(User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build());}//...
}

条件一:从自动配置源码中得知当 ClassPath 下存在 AuthenticationManager 类

条件二:当前项目中,系统没有提供 AuthenticationManager.class、 AuthenticationProvider.class、UserDetailsService.class、 AuthenticationManagerResolver.class 对应的 Bean 对象

这两个条件默认情况下都会满足,此时 Spring Security 会提供一个 InMemoryUserDetailManager 实例:

Untitled

@ConfigurationProperties(prefix = "spring.security")
public class SecurityProperties {private final User user = new User();public User getUser() {return this.user;}//....public static class User {private String name = "user";private String password = UUID.randomUUID().toString();private List<String> roles = new ArrayList<>();private boolean passwordGenerated = true;//get set ...}}

这就是默认生成 user 以及 uuid 密码的过程!另外看明白源码之后,就知道只要在配置文件中加入以下配置就可以对内存中的用户名和密码进行覆盖。

Untitled

总结

AuthenticationManager、ProviderManger、以及 AuthenticationProvider 的关系

Untitled

WebSecurityConfigurerAdapter:扩展 Spring Security 的所有默认配置

Untitled

UserDetailService:用来修改默认认证的数据源信息

Untitled

相关文章:

第一章 初识 Spring Security

第一章 初识 Spring Security 1、权限管理 权限管理 基本上涉及到用户参与的系统都要进行权限管理&#xff0c;权限管理属于系统安全的范畴&#xff0c;权限管理实现了对用户访问系统的控制&#xff0c;按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资…...

2023-02-20 关于回朔的思考

摘要: 考虑命运来回动荡交织&#xff0c;一些新的规划在不断的扩充, 而一些历史则开始陷入回朔。 有必要对历史和过往做一些规划和思考。 需要注意在这个阶段, 第一优先级是在反刍中将其最大化。 理论层: 一. 数据库的基础理论 ANSI SQL到词法解析和语法解析mysql的SQL层对…...

推荐系统[八]算法实践总结V1:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】

0.前言:召回排序流程策略算法简介 推荐可分为以下四个流程,分别是召回、粗排、精排以及重排: 召回是源头,在某种意义上决定着整个推荐的天花板;粗排是初筛,一般不会上复杂模型;精排是整个推荐环节的重中之重,在特征和模型上都会做的比较复杂;重排,一般是做打散或满足…...

适合初学者的超详细实用调试技巧(下)

我们日常写代码的时候&#xff0c;常常会遇到bug的情况&#xff0c;这个时候像我这样的初学者就会像无头苍蝇一样这里改改那里删删&#xff0c;调试的重要性也就显现出来&#xff0c;这篇文章接着上文来讲解。 上文地址&#xff1a;(8条消息) 适合初学者的超详细实用调试技巧&…...

C# String与StringBuilder 的区分

重点 1)它是比较的栈里面的值是否相等(值比较) 2)Equals它比较的是堆里面的值是否相等(引用地址值比较) 3)Object.ReferenceEquals(obj1,obj2)它是比较的是内存地址是否相等 问题描述&#xff1a; 今日提交代码时候&#xff0c;被检测工具发出修改建议。遂补充一下知识 1.什么…...

【麒麟】基于GPS北斗卫星技术的NTP网络时间服务器

【麒麟】基于GPS北斗卫星技术的NTP网络时间服务器 【麒麟】基于GPS北斗卫星技术的NTP网络时间服务器 麒麟系统NTP授时方案 设计思路&#xff1a; 在通用的麒麟服务器内部固定一块北斗卫星接收模块并引出卫星天线接口&#xff0c;卫星模块接收北斗卫星数据并解码输出时间数据&…...

“互联网+”下劳动关系认定的现状

1. 劳动关系的认定标准。依据目前我国法律的有关规定, 判定劳动关系存在两种情况:其一, 在有书面劳动合同的情况下, 这时应以书面合同作为认定标准;其二, 在没有书面合同的情况下, 则依据2005年劳社部的《关于确立劳动关系有关事项的通知》来认定, 其中第一条:“用人单位招用劳…...

LPWAN及高效弹性工业物联网核心技术方案

20多年前的一辆拖拉机就是一个纯机械的产品&#xff0c;里面可能并没有电子或者软件的构成&#xff1b;而随后随着软件的发展&#xff0c;拖拉机中嵌入了软件&#xff0c;它能控制发动机的功率及拖拉机防抱死系统&#xff1b;接下来&#xff0c;通过融入各种软件&#xff0c;拖…...

OPTIONS FMTSEARCH

FMTSEARCH 指定要检索的格式目录列表&#xff0c;语法如下&#xff1a;OPTIONS FMTSEARCH(catalog-specification-1<catalog-specification-2 … >);使用PROC FORMAT时可以定义格式目录&#xff0c;LIBRARYlibref或LIBRARYlibref.catalog。格式目录可以是libref或libref.…...

Python3 pip

Python3 pip pip 是 Python 包管理工具&#xff0c;该工具提供了对 Python 包的查找、下载、安装、卸载的功能。 软件包也可以在 https://pypi.org/ 中找到。 目前最新的 Python 版本已经预装了 pip。 注意&#xff1a;Python 2.7.9 或 Python 3.4 以上版本都自带 pip 工具…...

【2023-02-20】JS逆向之翼支付

提示&#xff1a;文章仅供参考&#xff0c;禁止用于非法途径 文章目录前言分析总结前言 真的好久没更了…… 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 分析 进到网页&#xff0c;加载两个接口 applyLoginFactor 接口返回一个RSA公钥&#xff0…...

假如面试官问你Babel的原理该怎么回答

1. 什么是 Babel 简单地说&#xff0c;Babel 能够转译 ECMAScript 2015 的代码&#xff0c;使它在旧的浏览器或者环境中也能够运行。 // es2015 的 const 和 arrow function const add (a, b) > a b;// Babel 转译后 var add function add(a, b) {return a b; };Babel…...

深入Spring底层透析Bean创建过程之拨云见日篇

目录前言一.BeanFactory快速入门1. BeanFactory创建Bean2. BeanFactory和ApplicationContext的关系3. 和ApplicationContext区别(高频问点)4. BeanFactory的继承体系5. ApplicationContext的继承体系二.Bean实例化的基本流程&#xff08;重点)前言 首先感谢您的阅览&#xff0…...

8 狗监控的封装

概述 为了保证嵌入式程序能够长时间稳定地运行,需要加入狗监控机制。狗监控的原理为:应用程序需要每隔一段时间来喂狗或保活,如果应用程序崩溃或者内核崩溃,导致长时间无法喂狗,则狗将超时,会自动重启系统。部分IPC芯片提供了硬件狗,对于没有硬件狗的,需要自行实现软件…...

基于卷积神经网络图像风格迁移系统的设计与实现(flask系统)

1.摘要 Leon Gatys 等人研发的深度神经网络使用神经的表达来分离任意图片的内容和风格&#xff0c;为生成艺术图片提供一个神经算法。本文基于Style Transfer算法&#xff0c;使用风格成本函数训练CNN&#xff0c;用卷积神经网络提取图像特征&#xff0c;依次提取内容图像的内…...

【1】linux命令每日分享——mkdir

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…...

实例2:树莓派GPIO控制外部LED灯闪烁

实例2&#xff1a;树莓派GPIO控制外部LED灯闪烁 实验目的 通过背景知识学习&#xff0c;了解四足机器人mini pupper搭载的微型控制计算机&#xff1a;树莓派。通过树莓派GPIO操作的学习&#xff0c;熟悉GPIO的读写控制。通过外部LED灯的亮灭控制&#xff0c;熟悉树莓派对外界…...

详解可变形注意力模块(Deformable Attention Module)

Deformable Attention&#xff08;可变形注意力&#xff09;首先在2020年10月初商汤研究院的《Deformable DETR: Deformable Transformers for End-to-End Object Detection》论文中提出&#xff0c;在2022CVPR中《Vision Transformer with Deformable Attention》提出应用了De…...

Java数据结构中链表分割及链表排序使用快速排序、归并排序、集合排序、迭代、递归,刷题的重点总结

本篇主要介绍在单链表进行分割&#xff0c;单链表进行分隔并使用快速排序、归并排序、集合排序、迭代、递归等方法的总结&#xff0c;愿各位大佬喜欢~~ 86. 分隔链表 - 力扣&#xff08;LeetCode&#xff09; 148. 排序链表 - 力扣&#xff08;LeetCode&#xff09; 目录 一…...

音视频基础之音频编码原理简介

一&#xff1a;隐蔽信号 数字音频信号如果不加压缩地直接进行传送&#xff0c;将会占用极大的带宽。例如&#xff0c;一套双声道数字音频若取样频率为44.1KHz&#xff0c;每样值按16bit量化&#xff0c;则其码率为&#xff1a; 244.1kHz16bit1.411Mbit/s 如此大的带宽将给信号…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...