十、Spring Boot集成Spring Security之HTTP请求授权
文章目录
- 往期回顾:Spring Boot集成Spring Security专栏及各章节快捷入口
- 前言
- 一、HTTP请求授权工作原理
- 二、HTTP请求授权配置
- 1、添加用户权限
- 2、配置ExceptionTranslationFilter自定义异常处理器
- 3、HTTP请求授权配置
- 三、测试接口
- 1、测试类
- 2、测试
- 四、总结
往期回顾:Spring Boot集成Spring Security专栏及各章节快捷入口
- Spring Boot集成Spring Security专栏
- 一、Spring Boot集成Spring Security之自动装配
- 二、Spring Boot集成Spring Security之实现原理
- 三、Spring Boot集成Spring Security之过滤器链详解
- 四、Spring Boot集成Spring Security之认证流程
- 五、Spring Boot集成Spring Security之认证流程2
- 六、Spring Boot集成Spring Security之前后分离认证流程最佳方案
- 七、Spring Boot集成Spring Security之前后分离认证最佳实现
- 八、Spring Boot集成Spring Security之前后分离认证最佳实现对接测试
- 九、Spring Boot集成Spring Security之授权概述
- 十、Spring Boot集成Spring Security之HTTP请求授权
前言
本文介绍HTTP请求授权工作原理、配置及适用场景,配合以下内容观看效果更佳!!!
- 什么是授权,授权有哪些流程,Spring Security的授权配置有几种?请查看九、Spring Boot集成Spring Security之授权概述
- HTTP请求授权的实现原理是什么,如何配置HTTP请求授权?请查看十、Spring Boot集成Spring Security之HTTP请求授权
- 方法授权的实现原理是什么,如何配置方法授权?请查看十一、Spring Boot集成Spring Security之方法授权
- 如何实现基于RBAC模型的授权方式?请查看十二、Spring Boot集成Spring Security之基于RBAC模型的授权
一、HTTP请求授权工作原理
基于Spring Security最新的Http请求授权讲解,不再使用旧版的请求授权
- 授权过滤器AuthorizationFilter获取认证信息
- 调用RequestMatcherDelegatingAuthorizationManager的check方法验证该用户是否具有该请求的授权
- RequestMatcherDelegatingAuthorizationManager根据配置的请求和授权关系校验用户是否具有当前请求的授权并返回授权结果
- AuthorizationFilter处理授权结果,授权成功则继续调用过滤器链,否则抛出AccessDeniedException异常
- 认证失败时,ExceptionTranslationFilter处理AccessDeniedException异常,如果是当前认证是匿名认证或者RememberMe认证则调用AuthenticationEntryPoint的commence方法,否则调用AccessDeniedHandler的handler方法
- 工作原理图如下
二、HTTP请求授权配置
1、添加用户权限
package com.yu.demo.spring.impl;import com.yu.demo.entity.UserDetailsImpl;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.UUID;@Service
public class UserDetailsServiceImpl implements UserDetailsService {//@Autowired//private UserService userService;// @Autowired//private UserRoleService userRoleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//TODO 通过username从数据库中获取用户,将用户转UserDetails//User user = userService.getByUsername(username);//TODO 从数据库实现查询权限并转化为List<GrantedAuthority>//List<String> roleIds = userRoleService.listRoleIdByUsername(username);//List<GrantedAuthority> grantedAuthorities = new ArrayList<>(roleIds.size());//roleIds.forEach(roleId -> grantedAuthorities.add(new SimpleGrantedAuthority(roleId)));//return new User(username, user.getPassword(), user.getEnable(), user.getAccountNonExpired(), user.getCredentialsNonExpired(), user.getAccountNonLocked(), user.getAuthorities());//测试使用,指定权限List<GrantedAuthority> grantedAuthorities = new ArrayList<>();//与hasXxxRole匹配时添加ROLE_前缀grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));//与hasXxxAuthority匹配时原始值grantedAuthorities.add(new SimpleGrantedAuthority("OPERATE"));//{noop}不使用密码加密器,密码123的都可以验证成功UserDetailsImpl userDetails = new UserDetailsImpl(username, "{noop}123", true, true, true, true, grantedAuthorities);//userDetails中设置token,该token只是实现认证流程,未使用jwtuserDetails.setToken(UUID.randomUUID().toString());return userDetails;}}
2、配置ExceptionTranslationFilter自定义异常处理器
-
因AuthorizationFilter授权失败时会抛出异常,该异常由ExceptionTranslationFilter处理,所以要配置自定义的异常处理器。
-
自定义AccessDeniedHandler和AuthenticationEntryPoint异常处理器(可以用一个类实现认证授权相关的所有接口,也可以使用多个类分别实现)。
package com.yu.demo.spring.impl;import com.yu.demo.entity.ApiResp;
import com.yu.demo.entity.UserDetailsImpl;
import com.yu.demo.util.SpringUtil;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;@Component
public class LoginResultHandler implements AuthenticationSuccessHandler, LogoutSuccessHandler, AuthenticationEntryPoint, AuthenticationFailureHandler, AccessDeniedHandler {/*** 登录成功*/@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) authentication;UserDetailsImpl userDetailsImpl = (UserDetailsImpl) usernamePasswordAuthenticationToken.getPrincipal();//token返回到前端SpringUtil.respJson(response, ApiResp.success(userDetailsImpl.getToken()));}/*** 登录失败*/@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {SpringUtil.respJson(response, ApiResp.loginFailure());}/*** 登出成功*/@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {SpringUtil.respJson(response, ApiResp.success());}/*** 未登录调用需要登录的接口时*/@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {SpringUtil.respJson(response, ApiResp.notLogin());}/*** 已登录调用未授权的接口时*/@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {SpringUtil.respJson(response, ApiResp.forbidden());}
}
- 配置异常处理:
//异常处理配置.exceptionHandling(exceptionHandlingCustomizer -> exceptionHandlingCustomizer//授权失败处理器(登录账号访问未授权的资源时).accessDeniedHandler(loginResultHandler)//登录失败处理器(匿账号访问需要未授权的资源时).authenticationEntryPoint(loginResultHandler))
3、HTTP请求授权配置
- 本文使用最新的authorizeHttpRequests(AuthorizationFilter+AuthorizationManager)配置,不在使用authorizeRequests(FilterSecurityInterceptor+AccessDecisionManager+AccessDecisionVoter)
- 请求和授权配置成对出现,配置在前的优先级更高
- 请求种类
- antMatchers:Ant风格的路径模式,
?
(匹配一个字符)、*
(匹配零个或多个字符,但不包括目录分隔符)、**
(匹配零个或多个目录) - mvcMatchers:Spring MVC的路径模式,支持路径变量和请求参数
- regexMatchers:正则表达式路径模式
- requestMatchers:实现RequestMatcher自定义匹配逻辑
- anyRequest:未匹配的其他请求,只能有一个且只能放在最后
- antMatchers:Ant风格的路径模式,
- 授权种类
- permitAll:匿名或登录用户都允许访问
- denyAll:匿名和登录用户都不允许访问
- hasAuthority:有配置的权限允许访问,AuthorityAuthorizationManager校验
- hasRole:有配置的角色允许访问,ROLE_{配置角色}与用户权限匹配,AuthorityAuthorizationManager校验
- hasAnyAuthority:有配置的任意一个权限的允许访问,AuthorityAuthorizationManager校验
- hasAnyRole:有配置的任意一个角色允许访问,ROLE_{配置角色}与用户权限匹配,AuthorityAuthorizationManager校验
- authenticated:已认证(不包括匿名)的允许访问,AuthenticatedAuthorizationManager校验
- access:自定义授权处理
- 因authorizeHttpRequests不支持使用anonymous()的方式配置匿名访问,未自定义匿名角色时可以通过hasRole(“ANONYMOUS”)或者hasAuthority(“ROLE_ANONYMOUS”)或其他类似的方式实现允许匿名请求的设置
- http请求授权配置
//http请求授权.authorizeHttpRequests(authorizeHttpRequestsCustomizer -> authorizeHttpRequestsCustomizer//不允许访问.antMatchers("/test/deny").denyAll()//允许匿名访问.antMatchers("/test/anonymous").hasRole("ANONYMOUS")//允许访问.antMatchers("/test/permit").permitAll()//测试使用:拥有ADMIN角色.antMatchers("/test/admin")//拥有ROLE_ADMIN权限,配置的角色不能以ROLE_作为前缀.hasRole("ADMIN")//测试使用:拥有OPERATE权限.antMatchers("/test/operate")//拥有OPERATE权限.hasAuthority("OPERATE")//其他的任何请求.anyRequest()//需要认证,且不能是匿名.authenticated())
- 完整过滤器链配置
package com.yu.demo.config;import com.yu.demo.spring.filter.RestfulLoginConfigurer;
import com.yu.demo.spring.filter.RestfulUsernamePasswordAuthenticationFilter;
import com.yu.demo.spring.impl.LoginResultHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer;
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.SecurityContextRepository;@Configuration
@EnableWebSecurity
public class SecurityConfig {//登录参数用户名private static final String LOGIN_ARG_USERNAME = "username";//登录参数密码private static final String LOGIN_ARG_PASSWORD = "password";//登录请求类型private static final String LOGIN_HTTP_METHOD = HttpMethod.POST.name();//登录请求地址private static final String LOGIN_URL = "/login";//登出请求地址private static final String LOGOUT_URL = "/logout";@Autowiredprivate LoginResultHandler loginResultHandler;@Autowiredprivate SecurityContextRepository securityContextRepository;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity//禁用UsernamePasswordAuthenticationFilter、DefaultLoginPageGeneratingFilter、DefaultLogoutPageGeneratingFilter.formLogin(FormLoginConfigurer::disable)//禁用BasicAuthenticationFilter.httpBasic(HttpBasicConfigurer::disable)//禁用CsrfFilter.csrf(CsrfConfigurer::disable)//禁用SessionManagementFilter.sessionManagement(SessionManagementConfigurer::disable)//异常处理配置.exceptionHandling(exceptionHandlingCustomizer -> exceptionHandlingCustomizer//授权失败处理器(登录账号访问未授权的资源时).accessDeniedHandler(loginResultHandler)//登录失败处理器(匿账号访问需要未授权的资源时).authenticationEntryPoint(loginResultHandler))//http请求授权.authorizeHttpRequests(authorizeHttpRequestsCustomizer -> authorizeHttpRequestsCustomizer//不允许访问.antMatchers("/test/deny").denyAll()//允许匿名访问.antMatchers("/test/anonymous").hasRole("ANONYMOUS")//允许访问.antMatchers("/test/permit").permitAll()//测试使用:拥有ADMIN角色.antMatchers("/test/admin")//拥有ROLE_ADMIN权限,配置的角色不能以ROLE_作为前缀.hasRole("ADMIN")//测试使用:拥有OPERATE权限.antMatchers("/test/operate")//拥有OPERATE权限.hasAuthority("OPERATE")//其他的任何请求.anyRequest()//需要认证,且不能是匿名.authenticated())//安全上下文配置.securityContext(securityContextCustomizer -> securityContextCustomizer//设置自定义securityContext仓库.securityContextRepository(securityContextRepository)//显示保存SecurityContext,官方推荐.requireExplicitSave(true))//登出配置.logout(logoutCustomizer -> logoutCustomizer//登出地址.logoutUrl(LOGOUT_URL)//登出成功处理器.logoutSuccessHandler(loginResultHandler))//注册自定义登录过滤器的配置器:自动注册自定义登录过滤器;//需要重写FilterOrderRegistration的构造方法FilterOrderRegistration(){},在构造方法中添加自定义过滤器的序号,否则注册不成功.apply(new RestfulLoginConfigurer<>(new RestfulUsernamePasswordAuthenticationFilter(LOGIN_ARG_USERNAME, LOGIN_ARG_PASSWORD, LOGIN_URL, LOGIN_HTTP_METHOD), LOGIN_URL, LOGIN_HTTP_METHOD))//设置登录地址:未设置时系统默认生成登录页面,登录地址/login.loginPage(LOGIN_URL)//设置登录成功之后的处理器.successHandler(loginResultHandler)//设置登录失败之后的处理器.failureHandler(loginResultHandler);//创建过滤器链对象return httpSecurity.build();}}
三、测试接口
1、测试类
package com.yu.demo.web;import com.yu.demo.entity.ApiResp;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/hello")public ApiResp hello() {return ApiResp.success("hello");}/*** 匿名允许访问接口地址*/@GetMapping("/anonymous")public ApiResp anonymous() {return ApiResp.success("anonymous");}/*** 禁止访问接口地址*/@GetMapping("/deny")public ApiResp deny() {return ApiResp.success("deny");}/*** 允许访问接口地址*/@GetMapping("/permit")public ApiResp permit() {return ApiResp.success("permit");}/*** 拥有ADMIN角色或ROLE_ADMIN权限允许访问接口地址*/@GetMapping("/admin")public ApiResp admin() {return ApiResp.success("admin");}/*** 拥有OPERATE权限的允许访问接口地址*/@GetMapping("/operate")public ApiResp operate() {return ApiResp.success("operate");}}
2、测试
- 登录获取token
- admin接口测试
- 其他接口不在一一测试,有疑问或问题评论或私聊
四、总结
- 授权是拿用户的权限和可以访问接口的权限进行匹配,匹配成功时授权成功,匹配失败时授权失败
- 用户的权限对象是SimpleGrantedAuthority,字符串属性role
- 接口的role权限会通过ROLE_{role}转化为SimpleGrantedAuthority及其字符串属性role
- 接口的authority权限会直接转化为SimpleGrantedAuthority及其字符串属性role
- 拥有ROLE_ANONYMOUS权限或者ANONYMOUS角色可以访问匿名接口
- 后续会讲使用HTTP请求授权+自定义AuthorizationManager方式实现基于RBAC权限模型,欢迎持续关注
- 源码下载
相关文章:

十、Spring Boot集成Spring Security之HTTP请求授权
文章目录 往期回顾:Spring Boot集成Spring Security专栏及各章节快捷入口前言一、HTTP请求授权工作原理二、HTTP请求授权配置1、添加用户权限2、配置ExceptionTranslationFilter自定义异常处理器3、HTTP请求授权配置 三、测试接口1、测试类2、测试 四、总结 往期回顾…...

C#基础控制台程序
11.有一个54的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号。 12.从键盘输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。 13.输入一个数,判断它是奇数还是偶数,如果…...
【网络安全】CSRF
一、什么是CSRF CSRF(Cross-Site Request Forgery)是一种web应用程序安全漏洞,它利用了用户在已登录的状态下的信任,通过欺骗用户发送未经授权的请求来执行恶意操作。这种攻击的危害性取决于受害者在目标网站上的权限。 二、CSR…...

网络原理(一)—— http
什么是 http http 是一个应用层协议,全称为“超文本传输协议”。 http 自 1991 年诞生,目前已经发展为最主流使用的一种应用层协议。 HTTP 往往基于传输层的 TCP 协议实现的,例如 http1.0,http1.0,http2.0 http3 是…...

【实体配置】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列 …...

【Zookeeper】四,Zookeeper节点类型、通知、仲裁、会话
文章目录 Zookeeper的架构znode的版本Zookeeper的节点类型层级树状结构znode的不同类型 Zookeeper监视与通知通知的类型 Zookeeper的仲裁Zk的会话会话的生命周期 Zookeeper的架构 Zookeeper的服务器端运行两种模式:独立模式(standalone)和仲…...

【二分查找】力扣 34. 在排序数组中查找元素的第一个和最后一个位置
一、题目 二、思路 将题目转化为求解 target 和 target 1 的查找。分别采用最基础的二分查找即可。 三、题解 class Solution {public int[] searchRange(int[] nums, int target) {int n nums.length;int start lowerBound(nums, target);if (start n || nums[start] !…...

以达梦为数据库底座时部署的微服务页面报乱码,调整兼容模式
1.问题描述 部署微服务,文件、代码是延用的mysql类型的,部署前做了部分适配,但是在使用dm数据库进行安装的服务在页面上查询出的数据却都是乱码 2.查询官网,注意到一个参数COMPATIBLE_MODE兼容模式的配置 考虑是延用mysql&…...

Java设计模式 —— 【创建型模式】工厂模式(简单工厂、工厂方法模式、抽象工厂)详解
文章目录 前言一、简单工厂(静态工厂)1、概述2、代码实现3、优缺点 二、工厂方法模式1、概述2、代码实现3、优缺点 三、抽象工厂模式1、概述2、代码实现3、优缺点 四、总结 前言 先看个案例:【手机和手机店】在没有工厂的时候,手…...

KST-3D01型胎儿超声仿真体模、吸声材料以及超声骨密度仪用定量试件介绍
一、KST-3D01型胎儿超声仿真体模 KST—3D01型胎儿超声体模,采用仿羊水环境中内置胎龄为7个月大仿胎儿设计。用于超声影像系统3D扫描演示装置表面轮廓呈现和3D重建。仿羊水超声影像呈暗回声(无回波)特性,仿胎儿超声影像呈对比明显…...

网络原理->DNS协议和NAT协议解
前言 大家好我是小帅,今天我们来了解应用层的DNS协议和NAT技术 个人主页:再无B~U~G 文章目录 1.重要应⽤层协议DNS(Domain Name System)1.1 DNS背景 2. NAT技术3. 总结 1.重要应⽤层协议DNS(Domain Name System) DNS是⼀整套从域…...

基于yolov8、yolov5的100种中药材检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
项目介绍 项目中所用到的算法模型和数据集等信息如下: 算法模型: yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 , 直接提供最少两个训练好的模型。模型十分重要,因为有些同学的电脑没有 GPU࿰…...
RuoYi排序
RuoYi框架提供了多种实现排序的方法,以满足不同场景下的需求。这里简要介绍几种常见的排序实现方式: 1. 后端排序 1.1 使用startPagePlus方法 RuoYi框架中,可以通过对BaseController进行扩展来实现更灵活的分页与排序功能。例如࿰…...

Python+Pytest+Yaml+Allure数据参数化(DDT)数据驱动(一)
我们在做数据之前要知道几个问题 1、在代码层面怎么来数据驱动 2、yaml文件是什么 3、怎么用yaml文件实现对应的数据驱动 我们用的是pytest框架所以相对来说是简单的,我们通过pytest框架来实现,而框架中要数据驱动用到我们装饰器就好啦pytest.mark.p…...

BASLER工业相机维修不能触发拍照如何处理解决这个问题
BASLER工业相机维修不能触发拍照如何处理解决这个问题?最近遇到挺多工业相机维修咨询这个不能触发拍照的案例,所以今天优米佳维修的技术就抽空整理了这篇关于BASLER相机不能触发拍照的处理方法分享给大家。 当碰到巴斯勒工业相机不能触发拍照的问题&…...

Could not locate device support files.
报错信息:Failure Reason: The device may be running a version of iOS (13.6.1 17G80) that is not supported by this version of Xcode.[missing string: 869a8e318f07f3e2f42e11d435502286094f76de] 问题:xcode15升级到xcode16之后,13.…...
linux系统中常用文件日常使用命令记录
我们办公机是Ubuntu系统; 记录下工作中经常使用的几个文件或命令或一些零碎的知识点: (该文档会持续更新) 查看系统信息: uname -a cat /etc/product-info cat /etc/os-version 存放系统启停脚本 /etc/init.d/ 存放源…...

【C++打怪之路Lv16】-- map set
🌈 个人主页:白子寰 🔥 分类专栏:重生之我在学Linux,C打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~ 💡 坚持…...
TPU-MLIR 项目源码结构分析
TPU-MLIR 项目源码结构分析 本文用作学习记录和交流分享,主要内容为 TPU-MLIR 的源码框架分析和构建流程分析。源码地址:https://github.com/sophgo/tpu-mlir 文件结构 从最外层开始分析 envsetup.sh 该脚本用于配置和初始化开发环境,其中…...

IDEA Maven 打包找不到程序包错误或找不到符号,报错“程序包不存在“
参考文章:https://blog.csdn.net/yueeryuanyi/article/details/14211090 问题:IDEA Maven 打包找不到程序包错误或找不到符号,报错“程序包不存在“编译都没问题 解决思路 – >【清除缓存】 1. 强制刷新Maven缓存 选择 Maven 标签,Exe…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...