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

认证鉴权框架之—sa-token

一、概述

Satoken 是一个 Java 实现的权限认证框架,它主要用于 Web 应用程序的权限控制。Satoken 提供了丰富的功能来简化权限管理的过程,使得开发者可以更加专注于业务逻辑的开发。

二、逻辑流程

1、登录认证
(1)、创建token
当用户输入用户名和密码请求登录,后端验证用户名和密码的正确性。验证成功时,调用sa-token提供的登录接口,创建token

StpUtil.login(saBaseLoginUser.getId(), new SaLoginModel().setDevice(device).setExtra("name", saBaseLoginUser.getName()));

此方法,会自动创建token,并将token和会话session相关联,并且返回给前端的响应头中自动设置token:如下:
Response Header中返回set-cookie:token=token值
在这里插入图片描述
浏览器接受response后,会自动设置token的请求头,之后请求该域的接口时,会自动带上该请求头
Request Header中会携带token
在这里插入图片描述
如上的创建token,到给前端设置token的过程,只需要后端调用sa-token的登录接口,其他无需我们做任何事情。

(2)、创建当前用户的缓存
当调用完成sa-token的登录接口后,我们可以构建当前登录用户的对象SaBaseLoginUser,该对象可以添加权限,角色,组织等信息。
设置到sa-token的缓存中,这样在之后的接口中,我们需要获取当前用户信息或当前用户信息的权限等信息时,就可以直接从sa-token缓存中获取,就无需从数据库中再次查询。

设置当前用户的缓存
StpUtil.getTokenSession().set("loginUser", saBaseLoginUser);
获取当前用户的缓存
Object loginUser = StpUtil.getTokenSession().get("loginUser");
if (ObjectUtil.isNull(loginUser)) throw new CommonException("用户未登录");
SaBaseLoginUser saBaseLoginUser = (SaBaseLoginUser) loginUser;

注意,这里我们最好整合redis使用,否则会占用系统内存,占用内存多了就会造成性能瓶颈问题。同时整合redis也可以适用分布式多节点的服务。

2、查询权限(菜单和接口)
(1)、菜单权限
关于菜单,针对每一个前端页面的路由创建不同的菜单数据保存到数据库就行,之后针对角色进行授权即可。方法比较常见不在赘述。

(2)、接口权限
关于接口权限,sa-token自带一些注解类去管理接口权限,如:在controller类上使用@SaCheckRole注解或接口上使用@SaCheckPermission注解,标识该类或者接口为待认证的接口。

在spring容器初始化时,会初始化和注入所有的接口到容器中被spring所管理,可以通过springApplication上下文对象获取所有的RequestMappingHandlerMapping.class,即所有的controller类。在分别requestMappingHandlerMapping.getHandlerMethods()方法,即查询了所有的接口。
示例代码:

SpringUtil.getApplicationContext().getBeansOfType(RequestMappingHandlerMapping.class).values().forEach(requestMappingHandlerMapping -> requestMappingHandlerMapping.getHandlerMethods().forEach((key, value) -> {SaCheckPermission saCheckPermission = value.getMethod().getAnnotation(SaCheckPermission.class);if (ObjectUtil.isNotEmpty(saCheckPermission)) {PatternsRequestCondition patternsCondition = key.getPatternsCondition();if (patternsCondition != null) {String apiName = "未定义接口名称";ApiOperation apiOperation = value.getMethod().getAnnotation(ApiOperation.class);if (ObjectUtil.isNotEmpty(apiOperation)) {String annotationValue = apiOperation.value();if (ObjectUtil.isNotEmpty(annotationValue)) {apiName = annotationValue;}}
permissionResult.add(patternsCondition.getPatterns().iterator().next() + StrUtil.BRACKET_START + apiName + StrUtil.BRACKET_END);}}}));

3、授权
(1)、菜单授权
从数据库中查询所有的菜单数据,直接授权给角色即可。
(2)、接口授权
通过如上的方法,查询所有的接口权限(可以在容器初始化时保存到缓存中,减少查询次数)。之后做成表单,授权给角色或者指定账号即可。
在这里插入图片描述
4、鉴权
sa-token拦截器(SaInterceptor),我们只需要将拦截器注册到spring容器中,拦截所有的请求进行校验。

    @Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关,只是说明哪些接口不需要被拦截器拦截,此处都拦截)registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");}

sa-token会开放查询用户权限和角色的接口给我们重写,我们只需要覆写(自定义类实现StpInteface接口,覆写里面的方法)获取用户权限和角色的接口即可。
在这里插入图片描述
5、总结
如上,我们描述了一个完整示例。从创建token,前端在指定域内请求携带token。在到获取权限,授权和鉴权的全过程。授权信息一般可以保存到数据库中,通过sa-token官方的示例去覆写接口即可。其他只需要我们在合适的类上或者接口上添加注解就行。

三、代码示例
1、引入依赖
如果服务只有一个节点,仅配置第一个sa-token-spring-boot-starter就够用了,后两个依赖是将redis和sa-token整合,这样认证信息保存到redis中,跨节点权限认证时也不会出现问题。

<!--版本-->
<properties><sa.token.version>1.31.0</sa.token.version>
</properties><!-- sa-token -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>${sa.token.version}</version>
</dependency><!-- sa-token 整合 redis (使用jackson序列化方式) -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-dao-redis-jackson</artifactId><version>${sa.token.version}</version>
</dependency><!-- Sa-Token插件:权限缓存与业务缓存分离 -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-alone-redis</artifactId><version>${sa.token.version}</version>
</dependency>

2、配置文件

#########################################
# redis configuration
#########################################
spring:redis:database: 0host: 172.xx.xxx.xxport: 6379password:timeout: 10slettuce:pool:max-active: 200       // 连接池最大连接数max-wait: -1ms       // 连接池最大阻塞等待时间(负数表示不限制)max-idle: 10          // 连接池中最大空闲连接min-idle: 0           // 连接池中最小空闲连接
#########################################
# sa-token configuration
#########################################
sa-token:token-name: token     // token名称,即设置cookie的key值timeout: 2592000      // token有效期(秒),默认30天,-1代表永久有效activity-timeout: -1     // 最低活跃频率(秒),即超过这个时间没有访问系统会冻结该token,默认-1代表永不冻结is-concurrent: true    // 是否允许同一账号多地登录is-share: false      // 是否同一账号多地登录时共用同一个tokenmax-login-count: -1token-style: random-32is-log: false     // 是否输出操作日志is-print: false# sa-token alone-redis configurationalone-redis:database: 2    // 指定sa-token使用redis的哪一个库host: ${spring.redis.host}port: ${spring.redis.port}password: ${spring.redis.password}timeout: ${spring.redis.timeout}lettuce:pool:max-active: ${spring.redis.lettuce.pool.max-active}max-wait: ${spring.redis.lettuce.pool.max-wait}max-idle: ${spring.redis.lettuce.pool.max-idle}min-idle: ${spring.redis.lettuce.pool.min-idle}

如上配置的sa-token整合redis后,sa-token在创建token信息时,会自动将token信息保存到配置的redis中,无需我们在操作redis进行设置。
在这里插入图片描述
3、全局管理类
这里我们注册sa-token拦截器,注入StpLogic管理类(一般多种用户类型时需要),重写注解合并方法(父类有的注解也会被作用到子类处理),覆写sa-token的自定义接口查询用户角色和权限。

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.strategy.SaStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import cn.nivic.common.auth.enums.SaClientTypeEnum;
import cn.nivic.common.auth.util.StpClientLoginUserUtil;
import cn.nivic.common.auth.util.StpLoginUserUtil;
import java.util.List;/*** SaToken鉴权配置**/
@Configuration
public class AuthConfigure implements WebMvcConfigurer {/*** 注册Sa-Token的注解拦截器,打开注解式鉴权功能** 注解的方式有以下几中,注解既可以加在接口方法上,也可加在Controller类上:* 1.@SaCheckLogin: 登录认证 —— 只有登录之后才能进入该方法(常用)* 2.@SaCheckRole("admin"): 角色认证 —— 必须具有指定角色标识才能进入该方法(常用)* 3.@SaCheckPermission("user:add"): 权限认证 —— 必须具有指定权限才能进入该方法(常用)* 4.@SaCheckSafe: 二级认证校验 —— 必须二级认证之后才能进入该方法* 5.@SaCheckBasic: HttpBasic认证 —— 只有通过 Basic 认证后才能进入该方法** 在Controller中创建一个接口,默认不需要登录也不需要任何权限都可以访问的,只有加了上述注解才会校验**/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册注解拦截器,并排除不需要注解鉴权的接口地址 (与登录拦截器无关,只是说明哪些接口不需要被拦截器拦截,此处都拦截)registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");}@Bean("stpLogic")public StpLogic getStpLogic() {// 注入Sa-Token的StpLogic,客户端类型为B,处理B端用户的权限管理return new StpLogic(SaClientTypeEnum.B.getValue());}@Bean("stpClientLogic")public StpLogic getStpClientLogic() {// 注入Sa-Token的StpLogic,客户端类型为C,处理C端用户的权限管理        		return new StpLogic(SaClientTypeEnum.C.getValue());}@Beanpublic void rewriteSaStrategy() {// 重写Sa-Token的注解处理器,增加注解合并功能
// 这里的注解合并,即在继承体系中,也能获取到父类的注解实例。SaStrategy.me.getAnnotation = AnnotatedElementUtils::getMergedAnnotation;}/*** 权限认证接口实现类,集成权限认证功能
* 重写sa-token获取权限的接口,这里用户更具业务编码从数据库或者mongoDb中获取权限**/@Componentpublic static class StpInterfaceImpl implements StpInterface {/*** 返回一个账号所拥有的权限码集合*/@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {if (SaClientTypeEnum.B.getValue().equals(loginType)) {return StpLoginUserUtil.getLoginUser().getPermissionCodeList();} else {return StpClientLoginUserUtil.getClientLoginUser().getPermissionCodeList();}}/*** 返回一个账号所拥有的角色标识集合*/@Overridepublic List<String> getRoleList(Object loginId, String loginType) {if (SaClientTypeEnum.B.getValue().equals(loginType)) {return StpLoginUserUtil.getLoginUser().getRoleCodeList();} else {return StpClientLoginUserUtil.getClientLoginUser().getRoleCodeList();}}}}

4、注解和使用
(1)、@SaCheckLogin
放在controller的接口方法上,在调用到这个方法的时候,会校验用户是否登录,如果没有登录会直接报错,保障安全。一般放在关键接口上,一般接口无需如此。

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;@Api(tags = "B端登录控制器")
@RestController
@Validated
public class AuthController {/*** B端退出**/@ApiOperationSupport(order = 5)@ApiOperation("B端退出")@SaCheckLogin@GetMapping("/auth/b/doLogout")public CommonResult<String> doLogout() {StpUtil.logout();return CommonResult.ok();}/*** B端获取用户信息**/@ApiOperationSupport(order = 6)@ApiOperation("B端获取用户信息")@SaCheckLogin@GetMapping("/auth/b/getLoginUser")public CommonResult<SaBaseLoginUser> getLoginUser() {return CommonResult.data(authService.getLoginUser());}
}

(2)、@SaCheckPermission
放在controller的接口方法上,用户请求到这个方法时,会校验用户是否有这个接口的权限,没有权限会直接报错。常用在数据增删改查接口上。
至于sa-token获取接口权限:则是通过全局配置类中实现StpInterfaceImpl接口,获取当前用户的全部权限。

 @ApiOperationSupport(order = 1)@ApiOperation("获取机构分页")@SaCheckPermission("/biz/org/page")@GetMapping("/biz/org/page")public CommonResult<Page<BizOrg>> page(BizOrgPageParam bizOrgPageParam) {return CommonResult.data(bizOrgService.page(bizOrgPageParam));}

(3)、@SaCheckRole
@SaCheckRole是sa-token校验角色权限的注解,这里自定义注解SaClientCheckRole,在注解类上添加@SaCheckRole注解,从而达到sa-token校验角色的效果之后,还可以继续扩展注解功能。
前提:我们在全部配置类中调整了注解处理器为注解合并方式,这样sa-token在解析注解SaClientCheckRole时也会读取父类的SaCheckRole注解,从而达到校验的效果。
至于sa-token获取角色:则是通过全局配置类中实现StpInterfaceImpl接口,获取当前用户的全部角色。

@SaCheckRole(type = StpClientUtil.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE})
public @interface SaClientCheckRole {/*** 需要校验的角色标识* @return 需要校验的角色标识*/@AliasFor(annotation = SaCheckRole.class)String [] value() default {};/*** 验证模式:AND | OR,默认AND* @return 验证模式*/@AliasFor(annotation = SaCheckRole.class)SaMode mode() default SaMode.AND;}

四、sa-token基本组件
1、StpUtil
sa-token官方提供的工具类,提供了许多静态方法来帮助开发者快速地完成登录认证、权限校验等工作。例如,当用户登录时,可以通过 StpUtil.login(10001) 方法来标记当前会话已登录,并将账号ID写入会话中。设置当前用户信息缓存,可在之后的请求中获取登录用户信息等。具体实现还是依靠StpLogic完成的。

2、StpLogic
是 Sa-Token 框架的核心逻辑处理类,它封装了与认证和授权相关的具体实现。例如,当调用 StpUtil.logout() 方法时,实际上是调用了 StpLogic 的 logout 方法来处理会话注销的操作。此外,StpLogic 也用于实现登录、会话管理等核心逻辑。

3、StpInterface
是一个接口,它用于自定义权限认证的逻辑。开发者可以通过实现这个接口来提供自己的业务逻辑,比如实现 getPermissionList 方法来获取一个账号的所有权限列表,或者实现 getRoleList 方法来获取一个账号的角色列表。当 Sa-Token 需要校验权限时,它会调用这个接口的方法来获取相应的信息。

4、SaManager
一个管理类,它负责管理 Sa-Token 框架的各种全局组件,如全局配置 SaTokenConfig、持久化处理 SaTokenDao、权限认证 StpInterface、框架行为 SaTokenAction、上下文处理器 SaTokenContext 与 SaTokenSecondContext、认证活动监听 SaTokenListener、临时令牌验证 SaTempInterface、认证处理逻辑 StpLogic 等等。通过 SaManager,开发者可以方便地获取和管理这些组件。

5、SaStrategy
是一个策略类,它提供了一组策略方法,允许开发者自定义框架内部的一些行为。例如,你可以重写createToken方法来改变创建Token的策略,或者重写checkMethodAnnotation方法来改变如何校验一个Method 对象上的注解。

6、关联性
这些组件之间通过 SaManager 和 StpUtil 等工具类相互关联起来。例如,StpUtil 中的很多方法实际上都是调用了 StpLogic 的相应方法来实现其功能。而 StpLogic 在执行一些核心逻辑时,可能会调用 SaManager 中的组件,比如 SaTokenDao 来进行数据的持久化操作,或者调用 StpInterface 来获取权限信息。SaStrategy 则提供了一种机制,允许开发者在不改变 Sa-Token 框架核心逻辑的情况下调整某些行为。

7、流程图示例
StpUtil完成创建token,登录,登出等操作,具体通过StpLogic完成;
SaManager负责管理所有的Sa-token组件(StpLogic,StpInteface等…)
StpLogic负责实现所有的业务,会通过SaManager获取其他组件协调完成。
StpInterface给用户实现,提供具体的获取权限,角色等信息
SaStrategy指定策略,如注解合并等。
在这里插入图片描述

学海无涯苦作舟!!!

相关文章:

认证鉴权框架之—sa-token

一、概述 Satoken 是一个 Java 实现的权限认证框架&#xff0c;它主要用于 Web 应用程序的权限控制。Satoken 提供了丰富的功能来简化权限管理的过程&#xff0c;使得开发者可以更加专注于业务逻辑的开发。 二、逻辑流程 1、登录认证 &#xff08;1&#xff09;、创建token …...

Spring源码(十一):Spring MVC之DispatchServlet

本篇重点在于分析Spring MVC与Servlet标准的整合&#xff0c;下节将详细讨论Spring MVC的启动/加载流程、处理请求的具体流程。 一、介绍 Spring框架提供了构建Web应用程序的全功能MVC模块。通过策略接口 &#xff0c;Spring框架是高度可配置的&#xff0c;而且支持多种视图技…...

gitbash简单操作

https://blog.csdn.net/qq_42363495/article/details/104878170 工作区(空间)--暂存区--本地仓库--远程仓库 方法一&#xff1a;创建一个新的分支master&#xff0c;且远程库里没有该分支 只要将.gitignore文件放在文件夹下就可以&#xff0c;.gitignore是文本文档形式的文件…...

pnpm install安装element-plus的版本跟package.json指定的版本不一样

pnpm安装的版本不同于package.json中指定的版本可能是由于以下几种情况导致的&#xff1a; 依赖项冲突&#xff1a;当项目依赖的不同模块或库之间存在版本冲突时&#xff0c;pnpm可能会安装与package.json中指定的版本不同的版本。这可能是因为其他依赖项指定了不同的版本&…...

Java线程池的核心内容详解

文章内容已经收录在《面试进阶之路》&#xff0c;从原理出发&#xff0c;直击面试难点&#xff0c;实现更高维度的降维打击&#xff01; 目录 文章目录 目录Java线程池的核心内容详解线程池的优势什么场景下要用到线程池呢&#xff1f;线程池中重要的参数【掌握】新加入一个任…...

学习笔记——三小时玩转JQuery

也可以使用在线版&#xff0c;不过在线版需要有网络&#xff0c;网不好的情况下加载也不好 取值的时候也是只会取到有样式的纯文本&#xff0c;不会取到标签&#xff0c;会取到标签效果 prepend和append这两个方法用的比较多&#xff0c;before和affter用的比较少 想要把代码写…...

word试题转excel(最简单的办法,无格式要求)

分享早下班的终极秘诀~ 今天本来是个愉快的周五&#xff0c;心里想着周末的聚会和各种安排&#xff0c;然而突然一个加急任务砸了过来——要求在下周一提交一份精细整理的Excel表格&#xff01; 打开Word文件一看&#xff0c;成堆的试题内容需要整理到Excel里。看着满屏的题目…...

基于web的中小学成绩管理系统的设计与实现

目录 第一章 研究背景与意义 1.1 研究背景 1.2 研究意义 1.3 研究目的 第二章 关于系统的设计 2.1系统总体架构设计 2.2功能模块设计 2.3数据存储与管理 第三章 系统功能介绍 3.1成绩录入及发布 3.2班级管理和学生管理 3.3成绩分析结果展示 3.4用户反馈与改进 …...

Conmi的正确答案——在Kibana中进入Elasticsearch的索引管理页面

Elasticsearch版本&#xff1a;7.17.25 Kibana版本&#xff1a;7.17.25 注&#xff1a;索引即类似mysql的表。 0、进入首页 1、未创建任何“索引模式”时&#xff1a; 1.1、点击左边的三横菜单&#xff1b; 1.2、点击“Discover”&#xff0c;进入“发现”页面&#xff1b; 2…...

【JavaEE】【多线程】进阶知识

目录 一、常见的锁策略1.1 悲观锁 vs 乐观锁1.2 重量级锁 vs 轻量级锁1.3 挂起等待锁 vs 自旋锁1.4 普通互斥锁 vs 读写锁1.5 可重入锁 vs 不可重入锁1.6 不公平锁 vs 公平锁 二、synchronized特性2.1 synchronized的锁策略2.2 synchronized加锁过程2.3 其它优化措施 三、CAS3.…...

LeetCode100之三数之和(15)--Java

1.问题描述 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意 答案中不可以包含重复的三元组 示例1 输入&…...

并发编程三大特性--可见性和有序性

可见性&#xff1a; 什么是可见性&#xff1a; 可见性是指在数据在收到一个线程的修改时&#xff0c;其他的线程也可以得知并获取修改后的值的属性。这是并发编程的三大特性之一。 为了提高cpu的利用率&#xff0c;cpu在获取数据时&#xff0c;不是直接在主内存读取数据&…...

Android 使用ninja加速编译的方法

ninja的简介 随着Android版本的更迭&#xff0c;makefile体系逐渐增多&#xff0c;导致make单编模块的时间越来越长&#xff0c;每次都需要半个小时甚至更长时间&#xff0c;其原因为每次make都会重新加载所有mk文件&#xff0c;再生成ninja编译&#xff0c;此完整过程十分耗时…...

《Java 实现选择排序:原理剖析与代码详解》

目录 一、引言 二、选择排序原理 三、代码分析 1. 代码整体结构 2. main方法 3. sort方法&#xff08;选择排序核心逻辑&#xff09; 四、测试结果 一、引言 排序算法在计算机科学领域中是非常重要的一部分&#xff0c;它能够帮助我们将无序的数据按照特定的顺序进行排列…...

数据结构之双链表——考研笔记

文章目录 一.单链表VS双链表二.创建双链表&#xff08;带头结点&#xff09;三.双链表的插入四.双链表删除五.销毁双链表六.双链表遍历七. 循环链表八.静态链表1.用代码定义一个静态链表 一.单链表VS双链表 单链表中只包含指向它后继结点的指针&#xff0c;所以给定一个结点p找…...

Django视图写法

1.View&#xff1a;Django默认的视图基类,Django的HttpRequeset对象 2.APIView&#xff1a;REST-framework提供的所有视图的基类,继承自Django的View REST framework的Request对象 Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。 serializer Book…...

单臂路由实现不同VLAN之间设备通信

转载请注明出处 本实验为单臂路由配置&#xff0c;目的为让不同VLAN之间的设备能够互相通信。 1.首先&#xff0c;按照要求配置两个pc的ip地址&#xff0c;以pc0为例子&#xff1a; 2在交换机创建vlan10和vlan20 3.划分vlan&#xff0c;pc0为vlan10的设备&#xff0c;pc1为vla…...

Linux·进程控制(system V)

1. 共享内存 system V共享内存是最快的IPC形式&#xff0c;之前的管道是基于Linux内核开发的通讯方案&#xff0c;其读写接口都是现成的&#xff0c;因此内核设计者为了完成进程间通讯任务并不需要新增太多代码。而共享内存属于system V标准&#xff0c;是操作系统单独…...

华为云Stack名词解释

1、MRS MapReduce服务&#xff08;MRS&#xff09;是一种基于云计算平台的即开即用、稳定可靠、弹性伸缩、便捷管理的数据处理分析服务。 2、VBS 云硬盘备份服务&#xff08;VBS&#xff0c;Volume Backup Service&#xff09;可为云硬盘&#xff08;EVS&#xff0c;Elastic…...

YoloV9改进策略:上采样改进|CARAFE,轻量级上采样|即插即用|附改进方法+代码

论文介绍 CARAFE模块概述&#xff1a;本文介绍了一种名为CARAFE&#xff08;Content-Aware ReAssembly of FEatures&#xff09;的模块&#xff0c;它是一种用于特征上采样的新方法。应用场景&#xff1a;CARAFE模块旨在改进图像处理和计算机视觉任务中的上采样过程&#xff0…...

【C++】多态的语法与底层原理

1.多态的概念 1.1 概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会 产生出不同的状态。 举个例子&#xff1a;在现实当中&#xff0c;我们去火车站买票&#xff0c;一般都分三种情况&…...

RTP和RTCP的详细介绍及其C代码示例

RTP和RTCP的详细介绍及其C代码示例 RTP和RTCP简介RTP协议详解RTCP协议详解RTP和RTCP之间的关系C代码示例RTP和RTCP简介 RTP(Real-time Transport Protocol,实时传输协议)和RTCP(Real-time Transport Control Protocol,实时传输控制协议)是流媒体传输中常用的两个协议。R…...

深入浅出了解AI教育发展与落地应用情况

2023年,是生成式AI能力涌现的一年,通用大模型是其中的主旋律。经过一年的发展,通用大模型格局已初步形成,生成式AI也从能力展示走向应用落地。进入2024年,对生成式AI的讨论和实践也都转向如何赋能产业。相比于通用大模型,进入产业内的大模型需要的是对行业的Know-How,以…...

Hive数据库操作语法

数据类型 内部表和外部表 内部表 &#xff08;CREATE TABLE table_name ......&#xff09;未被external关键字修饰的即是内部表&#xff0c; 即普通表。 内部表又称管理表,内部表数据存储的位置由hive.metastore.warehouse.dir参数决定&#xff08;默认&#xff1a;/user/h…...

容器架构-Docker的成长之路

目录 1. 什么是容器 2. 容器 vs 虚拟机 3. Docker极速上手指南 环境准备 3.1 配置docker源 3.2 下载镜像加速的配置 3.3 下载自动补全工具 4. Docker C/S架构 5. Docker的镜像管理 5.1 下载nginx:alpine镜像并查看 5.2 sl大法 5.3 删除镜像 5.4 镜像清理用的命令 5…...

关于我、重生到500年前凭借C语言改变世界科技vlog.14——常见C语言算法

文章目录 1.冒泡排序2.二分查找3.转移表希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 根据当前所学C语言知识&#xff0c;对前面知识进行及时的总结巩固&#xff0c;出了这么一篇 vlog 介绍当前所学知识能遇到的常见算法&#xff0c;这些算法是…...

简记Vue3(三)—— ref、props、生命周期、hooks

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

ARM cpu算力KDMIPS测试

一、引言 KDMIPS(KiloDhrystone Million Instructions Per Second)是一种衡量处理器性能的指标,它表示处理器每秒钟可以执行多少百万条Dhrystone指令。 二、测试说明 1、将cpu模式调整为perfermance 2、将cpu的频率和gpu的频率调大最大 3、将ddr和各core的电压和频率调大最…...

自杀一句话木马(访问后自动删除)

在做安全测试时&#xff0c;例如文件上传时就要上传可以解析的脚本文件解析证明存在漏洞&#xff0c;这个时候就需要(访问后自动删除文件的一句话木马) PHP <?php echo md5(1);unlink(__FILE__); ?> 访问后自动删除...

Nginx 反向代理(解决跨域)

文章目录 前言一、同源策略二、跨域是什么&#xff1f;三、Nginx解决跨域1.前端示例代码2.说明 四、nginx反向代理配置五、启动nginx六、最终效果总结 前言 Nginx反向代理解决跨域 一、同源策略 定义&#xff1a;同源策略&#xff08;Same-Origin Policy&#xff09;是指浏览…...