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

Shiro学习(六):Shiro整合CAS实现单点登录

一、单点登录介绍

       单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。

      SSO的定义是在多个[应用],用户只需要登录一次就可以访问所有相互信任的应用系统。

      一般这种单点登录的实现方案,分为两种,即:中心化方式 与 去中心化方式;两者核心区别‘

     是对身份的认证操作是否集中。

1、中心化方式

      中心化所有认证请求统一交由一个中央认证服务器(中心)(如CAS Server、Keycloak、

      Okta)处理系统完全依赖该中心节点,以访问百度搜索为例看下中心化单点登录的认证流程,

      认证流程如下:

      

      1)用户访问“百度搜索”,被重定向到中央认证服务器登录,先发起认证请求

      2)认证通过后,服务器生成全局票据(如:Token),并返回给用户。

      3)用户访问“百度网盘”时,百度网盘应用向中央服务器验证Token有效性

      4)所有应用的认证状态由中央服务器统一维护(如Session或Token注销)

2、去中心化方式

      去中心化认证分散,无单一中心节点,依赖分布式协议或密码学技术实现信任传递;去中心

      化一般是通过JWT来实现的,以百度搜索为例看下去中心化的认证流程,如下所示:

      

      1)用户首次登录后,认证服务器签发一个自包含的JWT令牌(含用户信息、签名、过期时

            间)。

      2)用户访问“百度网盘”时直接携带JWT,“百度网盘”应用通过本地验证JWT令牌

      3)各应用独立验证JWT令牌有效性,无需实时依赖中心认证节点

3、中心化与去中心化的优缺点

     1)中心化方式:

           缺点:

               存在单点故障,单台服务的访问压力较大,每次请求认证身份都需要访问认证服务器,

               导致压力相对比较大,效率也比较低。

           优点:

               集中管理,用户权限、会话生命周期统一控制,安全性高。

              一致性,所有应用共享同一套认证逻辑,维护简单。

          中心化适用场景:

                  企业内部系统、封闭生态(如公司内网、校园网)

          中心化方式的实现方案:

                    (1)CAS

                    (2)SAML

                    (3)部分OAuth 2.0实现(如授权服务器集中管理)

      2)去中心化方式:

            缺点:

                    撤销困难,JWT过期前无法强制失效,需依赖短有效期或黑名单。

                    实现复杂,需处理分布式信任问题(如密钥分发、共识机制)  

            优点:

                    不存在单点故障,并且在访问时,可以减少网络IO所占用的时间,并且针对认证服务

                   器没有请求压力。去中心化的方式一般采用JWT实现

            适用场景:

                  区块链应用、物联网(IoT)、开放生态(如Web3)

二、搭建CAS服务

1、CAS介绍

      CAS是一个开源项目,CAS是应用于企业级别的单点登录的服务,CAS分为CAS Server,

      CAS Client;

      CAS Server是需要一个单独部署的Web工程

      CAS Client是一个项目中的具体业务服务,并且在需要认证或授权时,找到CAS Server即

      可整体CAS的认证和授权流程就是中心化的方式

    

2、搭建CAS

     CAS Server的5.x版本更改为使用gradle构建,平时更多的是使用Maven,这里采用CAS的4.x

     版本

     下载CAS:https://github.com/apereo/cas/archive/refs/tags/v4.1.10.zip

      CAS下载完成后使用IDEA打开CAS Server,并修改一些配置信息,将CAS Server进行打包,

      扔到Tomcat服务中运行   

2.1、使用IDEA打开CAS

        CAS下载后,我们只需要关注 cas-server-webapp 

        CAS默认只支持HTTPS协议,我们需要修改一些配置,让CAS支持http,具体修改如下

        1)修改 Apereo-10000002.json

              将 Apereo-10000002.json 中的serviceId的值修改成匹配Http协议

              

        2)HTTPSandIMAPS-10000001.json

             将 HTTPSandIMAPS-10000001.json 中的serviceId的值修改成匹配Http协议

             

       3)ticketGrantingTicketCookieGenerator.xml

            将id=ticketGrantingTicketCookieGenerator 的<bean> 中的 p:cookieSecure 修改为false

            

       4)warnCookieGenerator.xml

             将id=warnCookieGenerator的<bean> 中的 p:cookieSecure 修改为false

             

       5)deployerConfigContext.xml

            在deployerConfigContext.xml中id=proxyAuthenticationHandler的<bean>中追加 

            p:requireSecure="false"

            

2.2、将项目进行打包,采用项目中的Maven插件,war的形式打包

         执行plugins中提供的war:war执行打包

2.3、将war包扔到Tomcat的webapps里,并运行即可

2.4、访问CAS Server首页,并且完成认证

         1)配置CAS默认用户名和密码

              

         2)浏览器访问http://localhost:8080/cas/login 访问CAS登录页面

              

              

三、Shiro + pac4j + CAS 实现单点登录

       注意:

            1)CAS只是用来做认证,授权还是要基于前边的Shiro

            2)shiro-cas 依赖包中虽然提供了基于CAS的Relam类 CasRelam ,但该类在1.2版本后

                  已经过期,不建议使用;CasRelam 中的注释中建议使用 buji-pac4j 提供的CasRelam

1、Shiro + pac4j + CAS 认证流程

     本质上和ShiroWeb的流程没有变化,只不过内部使用的一些Realm和过滤器交由pac4j提供;

     认证流程如下图所示:

     

     

 2、Shiro + pac4j + CAS 认证实现步骤

1)准备Spring boot环境,省略

3)导入依赖

 <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><dependency><groupId>io.buji</groupId><artifactId>buji-pac4j</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.pac4j</groupId><artifactId>pac4j-cas</artifactId><version>3.0.2</version></dependency></dependencies>

3)CAS必要相关配置

      

4)定义Relam

    定义 CasRelam,注意与前边springboot 整合shiro中的Relam 的区别;CasRelam 需要继

   承 Pac4j包下的 Pac4jRealm;Pac4jRealm已经实现了具体的认证流程,我们不需要重写认证;

   但授权流程需要我们重写;因为CAS只做认证,授权还是由Shiro 完成的,所以授权可以把前边

   CustRelam 中的授权方法直接拿过来,这里就省略了。

   示例代码如下:

/*** 自定义基于CAS的Relam,继承 Pac4jRealm** todo 注意:*    认证方法直接用父类 中的认证方法doGetAuthenticationInfo,不需要重写*    授权需要自己编写,授权操作跟前边 Shiro 授权操作一致,可以把前边的CustRelam 中的授权直接拿过来*/
@Component
public class CasRealm extends Pac4jRealm {/*** 授权操作,需要自己编写,并且也可以基于RedisSessionDAO实现缓存……* 授权操作跟前边 Shiro 授权操作一致,可以把前边的CustRelam 中的授权直接拿过来** @param principals* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// do something , find DB or Cachereturn null;}
}

5)配置Shiro

     在与 Pac4j 的配置中,与前边Springboot-shiro 的配置差不多,需要注意的是:

          (1)Subject 是使用CAS的,所以需要手动注入 SubjectFactory 工厂类,用于创建Subject

          (2)因为我们导入的包不是 spring-boot-shiro shiro整合springboot 的包,所以需要自己手

                   动配置过滤器,并指定过滤器名称为 “shiroFilter”类似于我们在shiro整合Web 时,在

                   web.xml配置的名称为“shiroFilter”的过滤器  proxyAuthenticationHandler

     Shiro配置如下:

@Configuration
public class ShiroConfig {//CAS服务地址@Value("${cas.server.url:http://localhost:8080/cas}")private String casServerUrl;@Value("${cas.project.url:http://localhost:81}")private String casProjectUrl;@Value("${cas.clientName:test}")private String clientName;/***  主体工厂*  todo 注意:*       这里认证时,Subject 需要使用 Pac4j 中的,所以这里需要手动注入*       Pac4j 包中的 SubjectFactory 用于生成 Subject*       将 SubjectFactory 交给 SecurityManager 管理* @return*/@Beanpublic SubjectFactory subjectFactory(){return new Pac4jSubjectFactory();}/*** 安全管理器* todo 注意: 还是使用shiro包下的 SecurityManager** @param casRealm* @param subjectFactory Subject 需要使用 Pac4j 中的SubjectFactory,用于生成 Subject* @return*/@Beanpublic SecurityManager securityManager(CasRealm casRealm,SubjectFactory subjectFactory){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(casRealm);securityManager.setSubjectFactory(subjectFactory);return securityManager;}/*** 配置核心过滤器* 因为我们导入的包不是 spring-boot-shiro shiro整合springboot 的包,所以需要自己* 手动配置过滤器,并指定过滤器名称为 “shiroFilter”* 类似于我们在shiro整合Web 时,在web.xml配置的名称为“shiroFilter”的过滤器** @return*/@Beanpublic FilterRegistrationBean filterRegistrationBean(){FilterRegistrationBean filterRegistration =new FilterRegistrationBean();filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));filterRegistration.addUrlPatterns("/*");return filterRegistration;}/*** shiroFilter核心配置* @return*/@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager, Config config){ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();factoryBean.setSecurityManager(securityManager);putFilterChain(factoryBean);// 声明好pac4j提供的过滤器后Map<String, Filter> filters = factoryBean.getFilters();//1. 准备SecurityFilterSecurityFilter securityFilter = new SecurityFilter();securityFilter.setConfig(config);securityFilter.setClients(clientName);filters.put("security",securityFilter);//2. 设置回调的拦截器CallbackFilter callbackFilter = new CallbackFilter();callbackFilter.setConfig(config);callbackFilter.setDefaultUrl(casProjectUrl);filters.put("callback",callbackFilter);//3. 退出登录LogoutFilter logoutFilter = new LogoutFilter();logoutFilter.setConfig(config);logoutFilter.setCentralLogout(true);logoutFilter.setLocalLogout(true);logoutFilter.setDefaultUrl(casProjectUrl + "/callback?client_name=" + clientName);filters.put("logout",logoutFilter);return factoryBean;}/*** 构建过滤器链* @param factoryBean*/private void putFilterChain(ShiroFilterFactoryBean factoryBean) {Map<String,String> filterChain = new LinkedHashMap<>();// 后面在声明好pac4j提供的过滤器后,需要重新设置!filterChain.put("/test","security");filterChain.put("/logout","logout");filterChain.put("/callback","callback");//采用 pac4j提供的过滤器进行校验//filterChain.put("/**","security");//放行,shiro的过滤器filterChain.put("/**","anon");factoryBean.setFilterChainDefinitionMap(filterChain);}}

6)自定义 CasClient

     自定义需要继承类  CasClientorg.pac4j.cas.client.CasClient,并重写方法getRedirectAction,

     用于处理退出后的重定向,让点击退出登录时,重定向到登录页面,示例代码如下:

     

public class CasClient extends org.pac4j.cas.client.CasClient {public CasClient() {super();}public CasClient(CasConfiguration configuration) {super(configuration);}@Overridepublic RedirectAction getRedirectAction(final WebContext context) {init();AjaxRequestResolver ajaxRequestResolver = getAjaxRequestResolver();RedirectActionBuilder redirectActionBuilder = getRedirectActionBuilder();// it's an AJAX request -> appropriate actionif (ajaxRequestResolver.isAjax(context)) {logger.info("AJAX request detected -> returning the appropriate action");RedirectAction action = redirectActionBuilder.redirect(context);cleanRequestedUrl(context);return ajaxRequestResolver.buildAjaxResponse(action.getLocation(), context);}// authentication has already been tried -> unauthorizedfinal String attemptedAuth = (String) context.getSessionStore().get(context, getName() + ATTEMPTED_AUTHENTICATION_SUFFIX);if (CommonHelper.isNotBlank(attemptedAuth)) {cleanAttemptedAuthentication(context);cleanRequestedUrl(context);// 跑抛出异常,页面401,只修改这个位置!!// throw HttpAction.unauthorized(context);return redirectActionBuilder.redirect(context);}return redirectActionBuilder.redirect(context);}private void cleanRequestedUrl(final WebContext context) {SessionStore<WebContext> sessionStore = context.getSessionStore();if (sessionStore.get(context, Pac4jConstants.REQUESTED_URL) != null) {sessionStore.set(context, Pac4jConstants.REQUESTED_URL, "");}}private void cleanAttemptedAuthentication(final WebContext context) {SessionStore<WebContext> sessionStore = context.getSessionStore();if (sessionStore.get(context, getName() + ATTEMPTED_AUTHENTICATION_SUFFIX) != null) {sessionStore.set(context, getName() + ATTEMPTED_AUTHENTICATION_SUFFIX, "");}}
}

7)配置Pac4j

@Configuration
public class Pac4jConfig {//cas服务地址@Value("${cas.server.url:http://localhost:8080/cas}")private String casServerUrl;//CA回调地址@Value("${cas.project.url:http://localhost:81}")private String casProjectUrl;//客户端名称@Value("${cas.clientName:test}")private String clientName;/*** 核心Config* CAS服务的配置信息** @param casClient* @return*/@Beanpublic Config config(CasClient casClient){Config config = new Config(casClient);return config;}/*** casClient,主要设置回调* @param casConfiguration* @return*/@Beanpublic CasClient casClient(CasConfiguration casConfiguration){CasClient casClient = new CasClient(casConfiguration);// 设置CAS访问后的回调地址casClient.setCallbackUrl(casProjectUrl + "/callback?client_name=" + clientName);casClient.setName(clientName);return casClient;}/*** CAS服务地址* @return*/@Beanpublic CasConfiguration casConfiguration(){CasConfiguration casConfiguration = new CasConfiguration();// 设置CAS登录页面casConfiguration.setLoginUrl(casServerUrl + "/login");// 设置CAS协议casConfiguration.setProtocol(CasProtocol.CAS20);//设置请求前缀,必须加“/”casConfiguration.setPrefixUrl(casServerUrl + "/");//true表示允许代理casConfiguration.setAcceptAnyProxy(true);return casConfiguration;}}

8)测试

     

     

    

相关文章:

Shiro学习(六):Shiro整合CAS实现单点登录

一、单点登录介绍 单点登录&#xff08;Single Sign On&#xff09;&#xff0c;简称为 SSO&#xff0c;是比较流行的企业业务整合的解决方案之一。 SSO的定义是在多个[应用]&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统。 一般这种单点登录的实现方案&…...

HAProxy-ACL实战篇

HAProxy-ACL实战篇 IP说明172.25.254.101客户端172.25.254.102haproxy服务器172.25.254.103web1172.25.254.104web2 ACL示例-域名匹配 # 172.25.254.102 [rootRocky ~]# cat /etc/haproxy/conf.d/test.cfg frontend magedu_http_portbind 172.25.254.102:80mode httpbalanc…...

以下是针对该 Ansible 任务的格式检查和优化建议

以下是针对该 Ansible 任务的格式检查和优化建议&#xff1a; 目录 一、格式检查原始代码问题分析修正后的标准格式 二、推荐增强功能1. 添加可执行权限2. 显式指定 Shell 解释器3. 添加错误处理 三、完整 Playbook 示例四、验证脚本兼容性五、常见错误总结 一、格式检查 原始…...

C++语言的测试覆盖率

C语言的测试覆盖率分析与实践 引言 在软件开发过程中&#xff0c;测试覆盖率是一项重要的质量指标&#xff0c;它帮助开发者评估代码的测试效果&#xff0c;确保软件的可靠性与稳定性。尤其在C语言的开发中&#xff0c;由于其复杂的特性和丰富的功能&#xff0c;测试覆盖率的…...

如何使用 DrissionPage 进行网页自动化和爬取

在这个技术博客中&#xff0c;我们将向大家展示如何使用 DrissionPage 进行网页自动化操作与数据爬取。DrissionPage 是一个基于 Playwright 的 Python 自动化工具&#xff0c;它允许我们轻松地控制浏览器进行网页爬取、测试以及自动化操作。与其他工具&#xff08;如 Selenium…...

设计模式 Day 3:抽象工厂模式(Abstract Factory Pattern)详解

经过前两天的学习&#xff0c;我们已经掌握了单例模式与工厂方法模式&#xff0c;理解了如何控制实例个数与如何通过子类封装对象的创建逻辑。 今天&#xff0c;我们将进一步深入“工厂”体系&#xff0c;学习抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&a…...

TensorRT 有什么特殊之处

一、TensorRT的定义与核心功能 TensorRT是NVIDIA推出的高性能深度学习推理优化器和运行时库&#xff0c;专注于将训练好的模型在GPU上实现低延迟、高吞吐量的部署。其主要功能包括&#xff1a; 模型优化&#xff1a;通过算子融合&#xff08;合并网络层&#xff09;、消除冗余…...

SQL注入-盲注靶场实战(手写盲注payload)--SRC获得库名即可

布尔盲注 进入页面 注入点 ’ and 11 and 12 得知为布尔盲注 库名长度 and length(database()) 8 抓包&#xff08;浏览器自动进行了url编码&#xff09;爆破 得知为 12 库名字符 1 and ascii(substr(database(),1,1))112 – q &#xff08;这里如果不再次抓包…...

http://noi.openjudge.cn/_2.5基本算法之搜索_1804:小游戏

文章目录 题目深搜代码宽搜代码深搜数据演示图总结 题目 1804:小游戏 总时间限制: 1000ms 内存限制: 65536kB 描述 一天早上&#xff0c;你起床的时候想&#xff1a;“我编程序这么牛&#xff0c;为什么不能靠这个赚点小钱呢&#xff1f;”因此你决定编写一个小游戏。 游戏在一…...

Windows Flip PDF Plus Corporate PDF翻页工具

软件介绍 Flip PDF Plus Corporate是一款功能强大的PDF翻页工具&#xff0c;也被称为名编辑电子杂志大师。这款软件能够迅速将PDF文件转换为具有翻页动画效果的电子书&#xff0c;同时保留原始的超链接和书签。无论是相册、视频、音频&#xff0c;还是Flash、视频和链接&#…...

Java八股文-List

集合的底层是否加锁也就代表是否线程安全 (一)List集合 一、数组 array[1]是如何通过索引找到堆内存中对应的这块数据的呢? (1)数组如何获取其他元素的地址值 (2)为什么数组的索引是从0开始的&#xff0c;不可以从1开始吗 (3)操作数组的时间复杂度 ①查找 根据索引查询 未…...

btrfs , ext4 , jfs , xfs , zfs 对比 笔记250406

btrfs , ext4 , jfs , xfs , zfs 对比 笔记250406 特性Btrfsext4JFSXFSZFS定位现代多功能传统稳定轻量级高性能大文件企业级存储最大文件/分区16EB / 16EB16TB / 1EB4PB / 32PB8EB / 8EB16EB / 25610⁵ ZB快照✅ 支持❌ 不支持❌ 不支持❌ 不支持✅ 支持透明压缩✅ (Zstd/LZO)❌…...

Meta上新Llama 4,到底行不行?

这周AI圈被Meta的“深夜突袭”炸开了锅。 Llama 4家族带着三个新成员&#xff0c;直接杀回开源模型战场&#xff0c;连扎克伯格都亲自站台喊话&#xff1a;“我们要让全世界用上最好的AI&#xff01;” 但别急着喊“王炸”&#xff0c;先看看它到底强在哪。 这次Meta玩了个狠招…...

显示器工艺简介

华星光电显示器的生产工艺流程介绍&#xff0c;从入厂原料到生产出显示器的整体工艺介绍 华星光电显示器的生产工艺流程主要包括以下几个阶段&#xff0c;从原材料入厂到最终显示器的生产&#xff1a; 原材料准备 玻璃基板&#xff1a;显示器的核心材料&#xff0c;通常采用超…...

音乐软件Pro版!内置音源,听歌自由,一键畅享!

今天给大家介绍一款超实用的音乐软件——LX音乐Pro版。原版LX音乐需要用户自行导入音源才能正常使用&#xff0c;但此次推出的Pro版已经内置了音源&#xff0c;省去了繁琐的操作步骤&#xff0c;使用起来更加便捷 这款软件不仅支持歌曲搜索&#xff0c;还能搜索歌单&#xff0c…...

Spring 中有哪些设计模式?

&#x1f9e0; 一、Spring 中常见的设计模式 设计模式类型Spring 中的应用场景单例模式创建型默认 Bean 是单例的工厂模式创建型BeanFactory、FactoryBean抽象工厂模式创建型ApplicationContext 提供多个工厂接口代理模式结构型AOP 动态代理&#xff08;JDK/CGLIB&#xff09;…...

R语言使用ggplot2作图

在ggplot2中&#xff0c;图是采用串联起来&#xff08;&#xff09;号函数创建的。每个函数修改属于自己的部分。比如&#xff0c;ggplot()geom()...... aes(x, y, colour a,shape a,size a.......) ggplot2中画图常用的五大块内容 数据(data)及一系列将数据中的变量对应到图…...

GenerationMixin概述

类 类名简单说明GenerateDecoderOnlyOutput继承自 ModelOutput&#xff0c;适用于非束搜索方法的解码器-only模型输出类。GenerateEncoderDecoderOutput继承自 ModelOutput&#xff0c;适用于非束搜索方法的编码器-解码器模型输出类。GenerateBeamDecoderOnlyOutput继承自 Mod…...

文心快码制作微信小程序

AI时代来临&#xff0c;听说Baidu Comate也推出了自家的编程工具Zulu&#xff0c;可以从零到一帮你生成代码&#xff0c;趁着现在还免费&#xff0c;试试效果如何。这里以开发一个敲木鱼的微信小程序为例 一、需求分析 写小程序需求文档 首先&#xff0c;第一步我要准确描述…...

flutter provider状态管理使用

在 Flutter 中&#xff0c;Provider 是一个轻量级且易于使用的状态管理工具&#xff0c;它基于 InheritedWidget&#xff0c;并提供了一种高效的方式来管理和共享应用中的状态。相比其他复杂的状态管理方案&#xff08;如 Bloc 或 Riverpod&#xff09;&#xff0c;Provider 更…...

C++——静态成员

目录 静态成员的定义 静态成员变量 编程示例 存在的意义 静态成员函数 类内声明 类外定义 编程示例 静态成员的定义 静态成员在C类中是一个重要的概念&#xff0c;它包括静态成员变量和静态成员函数。静态成员的特点和存在的意义如下&#xff1a; 静态成员变量 1…...

UDP学习笔记(四)UDP 为什么大小不能超过 64KB?

&#x1f310; UDP 为什么大小不能超过 64KB&#xff1f;TCP 有这个限制吗&#xff1f; 在进行网络编程或者调试网络协议时&#xff0c;我们常常会看到一个说法&#xff1a; “UDP 最大只能发送 64KB 数据。” 这到底是怎么回事&#xff1f;这 64KB 是怎么来的&#xff1f;TCP…...

Linux中用gdb查看coredump文件

查看dump的命令&#xff1a; gdb 可执行文件 dump文件路径查看函数调用栈 (gdb)bt查看反汇编代码 (gdb)disassemble查看寄存器的值 (gdb)info all-registers如果通过上述简单命令无法排查&#xff0c;还是通过-g参数编译带符号表的可执行文件&#xff0c;再用gdb查看...

PyTorch 深度学习 || 7. Unet | Ch7.1 Unet 框架

1. Unet 框架...

LeetCode 热题 100 堆

215. 数组中的第K个最大元素 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 **k** 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 …...

LeetCode栈 155. 最小栈

设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…...

Linux系统03---文件操作时间编程

目录 文件操作 1.1 缓冲区 1.2 基于缓冲区的文件操作---高级 IO 1.3 基于非缓冲区的文件操作—低级 IO 1.3.1 文件描述符 int fd; 1.3.2 函数名&#xff1a;open() 1.3.3 函数名&#xff1a;close() 1.3.4 函数名&#xff1a;write() 1.3.5 函数名&#xff1a;read(…...

4月5日作业

需求&#xff1a; 1.按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2.要求SW 1为VLAN 2/3的主根及主网关 SW2为VLAN 20/30的主根及主网关&#xff0c;SW1和 SW2互为备份 3.可以使用super vlan 4.上层通过静态路由协议完成数据通信过程 5.AR1为企业出口路由器…...

新一代AI架构实践:数字大脑AI+智能调度MCP+领域执行APP的黄金金字塔体系

新一代AI架构实践&#xff1a;数字大脑智能调度领域执行的黄金金字塔体系 一、架构本质的三层穿透性认知 1.1 核心范式转变&#xff08;CPS理论升级&#xff09; 传统算法架构&#xff1a;数据驱动 → 特征工程 → 模型训练 → 业务应用 新一代AI架构&#xff1a;物理规律建…...

低代码开发:重塑软件开发的未来

在数字化转型的浪潮中&#xff0c;企业对软件开发的需求呈爆炸式增长。然而&#xff0c;传统软件开发模式面临着开发周期长、成本高、技术门槛高等诸多挑战。低代码开发平台&#xff08;Low-Code Development Platform&#xff09;应运而生&#xff0c;它通过可视化编程和拖拽式…...

小型园区网实验作业

拓扑搭建&#xff1a; 实验需求&#xff1a; 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及网关 SW2 为VLAN 20/30 的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan 4、上层通过静态路由协议完成数据通信过程 5、A…...

Gateway 网关 快速开始

一、核心概念 路由&#xff08;route) 路由是网关中最基础的部分&#xff0c;路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真&#xff0c;则说明请求的 URL 和配置的路由匹配。 断言(predicates) 断言函数允许开发者去定义匹配 Http Request 中…...

C++中如何使用STL中的list定义一个双向链表,并且实现增、删、改、查操作

一、STL中的 list 是双向链表&#xff0c;但不是循环链表&#xff0c;通过指针访问结点数据&#xff0c;它的内存空间可以是不连续的&#xff0c;使用它能高效地进行各种操作。 二、代码 #include <bits/stdc.h> using namespace std;// 打印链表元素的函数 void print…...

shell脚本中捕获键盘中断信号trap

在 Shell 脚本中&#xff0c;可以通过 trap 命令捕获键盘中断信号&#xff08;通常是 SIGINT&#xff0c;即 CtrlC&#xff09;。以下是具体的实现方法&#xff1a; 1.使用 trap 捕获键盘中断信号 trap 命令用于捕获信号并执行相应的命令或函数。SIGINT&#xff08;信号编号为 …...

让ChatGPT用DeepReaserch指导进行学术写作

目录 ChatGPT在学术论文写作中的作用与分阶段提示词指南 1.选题阶段&#xff08;确定研究课题方向&#xff09; 2.文献综述阶段&#xff08;调研与综述已有研究&#xff09; 3.研究设计阶段&#xff08;设计研究方法与框架&#xff09; 4.撰写正文阶段&#xff08;撰写各部…...

Compose笔记(十四)--LazyColumn

这一节了解一下Compose中的LazyColumn&#xff0c;在Jetpack Compose 中&#xff0c;LazyColumn 是一个用于高效显示长列表或可滚动垂直布局的组件。它类似于传统 Android 开发中的 RecyclerView&#xff0c;但专为 Compose 的声明式 UI 框架设计&#xff0c;能够显著优化性能&…...

CNN-SE-Attention-ITCN多特征输入回归预测(Matlab完整源码和数据)

CNN-SE-Attention-ITCN多特征输入回归预测&#xff08;Matlab完整源码和数据&#xff09; 目录 CNN-SE-Attention-ITCN多特征输入回归预测&#xff08;Matlab完整源码和数据&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.一种适合光伏功率回归预测的高创…...

Spring Data JPA中的List底层:深入解析ArrayList的奥秘!!!

&#x1f31f; Spring Data JPA中的List底层&#xff1a;深入解析ArrayList的奥秘 &#x1f4a1; 你是否好奇过&#xff0c;为什么Spring Data JPA的查询方法返回的List<T>总是默认为ArrayList&#xff1f;本文将通过技术原理解析、验证实验和性能优化指南&#xff0c;为…...

redis高并发缓存架构与性能优化

Redlock实现原理 超过半数redis节点加锁成功才算成功加锁。 Redlock存在问题 如果主节点挂掉&#xff0c;还没有同步到从节点&#xff0c;重新选举出主节点&#xff0c;那加锁就没有加到这个新的主节点上。 如果增加redis主节点数&#xff0c;那么加锁的性能更差&#xff0c;要…...

解锁多邻国:全方位语言学习新体验

解锁多邻国&#xff1a;全方位语言学习新体验​ ​ 在数字化学习浪潮中&#xff0c;多邻国&#xff08;Duolingo&#xff09;凭借独特优势&#xff0c;成为全球超 5 亿用户的语言学习首选。这款 2012 年诞生于美国匹兹堡的应用&#xff0c;2019 年进入中国市场后&#xff0c;…...

Docker部署SeraXNG接入dify报错解决

报错&#xff1a; 设置授权 配置凭据后&#xff0c;工作区中的所有成员都可以在编排应用程序时使用此工具。 SearXNG base URL* 如何获取 PluginInvokeError: {"args":{},"error_type":"ToolProviderCredentialValidationError","message&q…...

Zookeeper的作用详解

Zookeeper作为分布式协调服务&#xff0c;在分布式系统中承担核心协调角色&#xff0c;其作用可归纳为以下核心功能模块&#xff1a; 一、分布式协调与同步 分布式锁管理 提供独占锁和共享锁&#xff0c;通过创建临时顺序节点实现锁的公平竞争。例如&#xff0c;客户端在/distr…...

高频面试题(含笔试高频算法整理)基本总结回顾34

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

Dify 与 n8n 对比分析:AI 应用开发与自动化工作流工具的深度比较

Dify 与 n8n 对比分析&#xff1a;AI 应用开发与自动化工作流工具的深度比较 摘要 本文对比分析了 Dify 和 n8n 两款工具的核心定位、功能特点、适用场景及技术门槛。Dify 专注于 AI 应用开发&#xff0c;适合快速搭建智能客服、知识库检索等场景&#xff1b;n8n 则定位于通用…...

Systemd构建容器化微服务集群管理系统

实训背景 你是一家云计算公司的 DevOps 工程师&#xff0c;需为某客户设计一套基于 Docker 的微服务集群管理系统&#xff0c;需求如下&#xff1a; 容器自启管理&#xff1a;确保三个服务&#xff08;webapp、api、redis&#xff09;在系统启动时自动运行。依赖顺序控制&…...

手搓多模态-04 归一化介绍

在机器学习中&#xff0c;归一化是一个非常重要的工具&#xff0c;它能帮助我们加速训练的速度。在我们前面的SiglipVisionTransformer 中&#xff0c;也有用到归一化层&#xff0c;如下代码所示&#xff1a; class SiglipVisionTransformer(nn.Module): ##视觉模型的第二层&am…...

nano 编辑器的使用

nano 编辑器的使用 1. 启动 nano2. 编辑文本3. 基本操作4. 保存和退出5. 其他常用快捷键6. 高级用法 nano 是一个简单易用的文本编辑器&#xff0c;适合初学者使用&#xff1a; 1. 启动 nano 在终端中输入 nano 命令&#xff0c;后面可以跟上你想要编辑的文件的名称。如果文件…...

如何搞定学习人工智能所需的数学?

一、明确AI所需的数学核心领域 AI的数学需求并非泛泛而谈&#xff0c;而是集中在几个核心领域。以下是按优先级排序的关键知识点&#xff1a; 线性代数 核心概念&#xff1a;向量、矩阵、特征值分解、奇异值分解&#xff08;SVD&#xff09;。应用场景&#xff1a;图像处理&a…...

TCP/IP五层协议

目录 1. 五层模型结构 2. 各层核心功能与协议 (1) 应用层&#xff08;Application Layer&#xff09; (2) 传输层&#xff08;Transport Layer&#xff09; (3) 网络层&#xff08;Network Layer&#xff09; (4) 数据链路层&#xff08;Data Link Layer&#xff09; (5…...

解决Opencv:TypeError: points is not a numerical tuple

最近刚开始学习Opencv&#xff0c;跟着b站阿婆主敲代码的时候&#xff0c;又又又又&#xff0c;又出现了bug&#xff0c;下面听我娓娓道来~~ --------------------------------------------------------------------------&#xff08;手动分界线&#xff09; 首先描述一下当时…...