微服务下的SpringSecurity认证端
从三板斧开始微服务下的SpringSecurity开始
一、引入组件包
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>
二、创建适配器
AuthorizationServerConfigurerAdapter是一个授权适配器,在这个适配器中有如下几个核心方法:
- ClientDetailsServiceConfigurer
用来配置客户端详情服务(ClientDetailsService),这里的配置表明不是任何人都可以来授权中心进行授权的,客户端详情信息在这里进行初始化,可以在内存中也可以来自于数据库,根据你自己的需要进行配置;一个ClientDetails标识一个客户端的详情描述,ClientDetails具体的属性如下:
| 属性名称 | 说明 | 
| clientId | 是一个唯一标识,用于标识客户 | 
| secret | 客户端的安全码;微信登录就有安全码 | 
| scope | 用来限制客户端的访问范围,如果为空,标识所有范围都可以访问 | 
| authrizedGrantTypes | 可以使用的授权类型(可选值范围:"authorization_code", "password", "client_credentials", "implicit", "refresh_token"),为空标识所有都支持;微信仅支持authorization_code; | 
| authorities | 客户端可以使用的权限(基于Spring Security Authorities) | 
| redirectUris | 回调地址,授权服务会往此地址回调推送客户端相关信息 | 
ClientDetails客户端详情可以在运行时进行更新,可以通过访问底层存储介质(例如:JdbcClientDetailsService)或者自己实现ClientRegisterationService接口或者实现ClientDetailsService来进行定制;
- AuthorizationServerSecurityConfigurer
配置令牌端点的安全约束;此接口包含了关于令牌管理的必要操作;
实现一个AuthorizationServerTokenServices接口需要继承DefaultTokenServices这个类;此类中包含了一些有用的实现,可以使用它来修改令牌的格式和令牌的存储模式;默认情况下,在创建一个令牌的时候,是使用随机值来进行填充的;这个类中完成了令牌管理的几乎所有事情,唯一需要依赖的是Spring容器中的一个TokenStore对象来定制令牌持久化;在Spring中有一个默认的TokenStore实现,即:ImMemoryTokenStore,这个类是将令牌保存到内存中,其他几个TokenStore实现类都可以根据自己的选择进行使用;
ImMemoryTokenStore:基于内存;
JdbcTokenStore:基于JDBC;
JwtTokenStore:基于JWT,这里啰嗦一下,此种类型时经常常用的类型,全称是“Json web Token”;是吧令牌信息全部编码到令牌本身,这样后端不需要维护令牌相关的信息,这是一大优势,当然缺点就是撤销令牌困难;传输占用空间比较大;
- AuthorizationServerEndpointsConfigurer
用来配置令牌的访问端点和令牌服务;授权类型(Grant Types)有如下几点:
| 授权类型 | 说明 | 
| authenticationManager | 认证管理器,如果你选择的是password(资源所有者密码)这个授权类型时,需要指定authenticationManager对象来进行鉴权 | 
| userDetailsService | 用户主体管理服务,在拥有自己UserDetailsService接口的实现,如果设置了这个属性,那么refresh_token刷新令牌的方式授权类型流程中会多一个检查的步骤,来确保是否依然有效 | 
| authorizationCodeServices | 用于authorization_code授权码模式,用来设置授权服务; | 
| implicitGrantService | 用于设置隐式授权模式的状态; | 
| tokenGranter | 这个是深度拓展时使用的;一旦设置,授权将会全部交由自己来掌控,会忽略以上几个属性; | 
  1 @Configuration2 @EnableAuthorizationServer3 @EnableConfigurationProperties(value = JwtCaProperties.class)4 public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {5 6     /**7      * 属性描述:注入数据源8      *9      * @date : 2020/4/12 0012 上午 11:5410      */11     private final DataSource dataSource;12 13     /**14      * 属性描述:JWT配置信息15      *16      * @date : 2020/4/12 0012 下午 10:4917      */18     private final JwtCaProperties jwtCaProperties;19 20     /**21      * 属性描述:用户信息处理22      *23      * @date : 2020/4/13 0013 上午 12:1224      */25     private final MyUserDetailServiceImpl myUserDetailServiceImpl;26 27     private final AuthenticationManager authenticationManager;28 29     /**30      * 功能描述:认证中心配置31      *32      * @author : XXSD33      * @date : 2020/4/12 0012 上午 11:5434      */35     public AuthServerConfig(DataSource dataSource, JwtCaProperties jwtCaProperties, MyUserDetailServiceImpl myUserDetailServiceImpl, AuthenticationManager authenticationManager) {36         this.dataSource = dataSource;37         this.jwtCaProperties = jwtCaProperties;38         this.myUserDetailServiceImpl = myUserDetailServiceImpl;39         this.authenticationManager = authenticationManager;40     }41 42     /**43      * 功能描述:配置第三方客户端的授权服务器安全配置44      * <br />45      * 用来配置令牌的端点安全约束46      *47      * @author : XXSD48      * @date : 2020/4/14 0014 下午 8:5549      */50     @Override51     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {52         //第三方客户端校验token需要带入 clientId 和clientSecret来校验53         security.checkTokenAccess("isAuthenticated()")54                 //来获取我们的tokenKey需要带入clientId,clientSecret55                 .tokenKeyAccess("isAuthenticated()");56         //使用表单认证的方式进行申领令牌57         security.allowFormAuthenticationForClients();58     }59 60     /**61      * 功能描述:配置接入的客户端62      * <br />63      * 用来配置客户端详情(ClientDetailsService),客户端详情杂这里进行初始化,可以把客户端详情信息写死或这通过64      * 数据库来存储详情信息65      *66      * @author : XXSD67      * @date : 2020/4/12 0012 上午 11:4968      */69     @Override70     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {71         /*//使用内存方式72         clients.inMemory()73                 .withClient("这里写客户端的ID")74                 .secret(new BCryptPasswordEncoder().encode("这里放入密码"))75                 .resourceIds("这里是客户端的资源列表")76                 //此客户端可以使用的授权类型77                 .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")78                 .scopes("允许的授权范围;没有什么特殊的意义,就是一个字符串,是自己根据我们后台的服务进行的一个划分而已")79                 //跳转到授权页面,是否显示授权页面;True标识默认用户同意,不显示授权页面80                 .autoApprove(false)81                 .redirectUris("这里写入你自己的回调地址");82                 //如果有更多的,在这里添加and83                 .and()84                 */85         clients.withClientDetails(clientDetails());86     }87 88     /**89      * 功能描述:配置Token信息90      * <br />91      * 用于配置令牌(Token)的访问端点和令牌服务(TokenService)92      *93      * @author : XXSD94      * @date : 2020/4/12 0012 下午 11:2395      */96     @Override97     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {98 99         /*
100         * AuthorizationServerEndpointsConfigurer对于不同类型的授权类别也需要配置不同的属性
101         * authenticationManager:
102         * 认证管理器,如果你选择的是password(资源所有者密码)这个授权类型时,需要指定authenticationManager对象来进行鉴权
103         * userDetailsService:
104         * 用户主体管理服务,在拥有自己UserDetailsService接口的实现,如果设置了这个属性,那么refresh_token刷新令牌的方式授权类型流程中会多一个检查的步骤,来确保是否依然有效
105         * authorizationCodeServices:
106         * 用于authorization_code授权码模式,用来设置授权服务;
107         * implicitGrantService:
108         * 用于设置隐式授权模式的状态;
109         * tokenGranter:
110         * 这个是深度拓展时使用的;一旦设置,授权将会全部交由自己来掌控,会忽略以上几个属性;
111         * */
112 
113         final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
114         //加入了之后增强器才有效果
115         tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnchaner(), jwtAccessTokenConverter()));
116         /*
117         * OAuth2.0已经默认配置了几个端点:
118         * /oauth/authorize:授权端点;
119         * /oauth/token:令牌端点;
120         * /oauth/confirm_access:用户确认授权提交的端点;
121         * /oauth/error:授权服务错误信息端点;
122         * /oauth/check_token:用于资源服务访问的令牌进行解析的端点;
123         * /oauth/token_key:使用JWT令牌需要用到的提供共有密钥的端点;
124         * */
125         endpoints
126                 //自定义重新定义端点路径
127 //                .pathMapping("")
128                 .tokenStore(tokenStore())
129                 .tokenEnhancer(tokenEnhancerChain)
130                 .userDetailsService(myUserDetailServiceImpl)
131                 //指定令牌管理服务
132 //                .tokenServices(tokenServices())
133                 //限制Token的信息允许提交的模式
134 //                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
135                 .authenticationManager(authenticationManager);
136     }
137 
138     /*private AuthorizationServerTokenServices tokenServices(){
139         final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
140         //客户端详情服务
141         defaultTokenServices.setClientDetailsService(clientDetails());
142         //令牌自动刷新
143         defaultTokenServices.setSupportRefreshToken(true);
144         //令牌存储策略
145         defaultTokenServices.setTokenStore(tokenStore());
146         //令牌默认有效期,当前设置为2小时;单位秒
147         defaultTokenServices.setAccessTokenValiditySeconds(7200);
148         //刷新令牌默认有效期,当前设置为3天;单位秒
149         defaultTokenServices.setRefreshTokenValiditySeconds(259200);
150 
151         return defaultTokenServices;
152     }*/
153 
154     /**
155      * 功能描述:注入基于JWT的自定义Token增强器
156      *
157      * @author : XXSD
158      * @date : 2020/4/12 0012 下午 11:21
159      */
160     @Bean
161     public AuthTokenEnchaner tokenEnchaner() {
162         return new AuthTokenEnchaner();
163     }
164 
165     /**
166      * 功能描述:Token存储控制对象
167      *
168      * @author : XXSD
169      * @date : 2020/4/12 0012 下午 1:01
170      */
171     @Bean
172     public TokenStore tokenStore() {
173         /*
174          * Token有如下几种方式存储:
175          * 1、基于内存:InMemoryTokenStore;
176          * 2、基于数据库:JdbcTokenStore;
177          * 3、基于Redis:RedisTokenStore;
178          * 4、基于JWT:JwtTokenStore
179          * 这里是基于JWT的
180          * */
181         return new JwtTokenStore(jwtAccessTokenConverter());
182     }
183 
184     /**
185      * 功能描述:Token与用户信息之间的转换器
186      *
187      * @author : XXSD
188      * @date : 2020/4/12 0012 下午 1:01
189      */
190     @Bean
191     public JwtAccessTokenConverter jwtAccessTokenConverter() {
192         final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
193         jwtAccessTokenConverter.setKeyPair(keyPair());
194         return jwtAccessTokenConverter;
195     }
196 
197     /**
198      * 功能描述:注入证书
199      *
200      * @author : XXSD
201      * @date : 2020/4/12 0012 下午 11:22
202      */
203     @Bean
204     public KeyPair keyPair() {
205         KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(jwtCaProperties.getKeyPairName()), jwtCaProperties.getKeyPairSecret().toCharArray());
206         return keyStoreKeyFactory.getKeyPair(jwtCaProperties.getKeyPairAlias(), jwtCaProperties.getKeyPairStoreSecret().toCharArray());
207     }
208 
209     /**
210      * 功能描述:客户端处理服务
211      *
212      * @author : XXSD
213      * @date : 2020/4/12 0012 上午 11:58
214      */
215     @Bean
216     public ClientDetailsService clientDetails() {
217         /*
218         * 如果是使用JDBC的方式进行,那么就需要在数据库中创建一个表
219         * 表的名称为:oauth_client_details
220         * CREATE TABLE `oauth_client_details` (
221             -- 标识客户端的ID;
222             `client_id` varchar(256) CHARACTER SET utf8 NOT NULL,
223             `resource_ids` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
224             -- 客户端安全码;
225             `client_secret` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
226             -- 用来限制客户端的访问范围,如果为空标识客户端拥有全部的访问范围
227             `scope` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
228             -- authrized;此客户端可以使用的授权类型,默认为空(全部可用:authorizaton_code、password、client_credentals、implicit、refresh_token);注:在微信中只支持authoriazton_code这一种
229             `authorized_grant_types` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
230             -- 回调的地址;授权服务会往此地址推送客户端的相关信息
231             `web_server_redirect_uri` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
232             -- 此客户端可以使用的权限(基于Spring Security authorities)
233             `authorities` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
234             `access_token_validity` int(11) DEFAULT NULL,
235             `refresh_token_validity` int(11) DEFAULT NULL,
236             `additional_information` varchar(4096) CHARACTER SET utf8 DEFAULT NULL,
237             -- 跳转到授权页面,是否跳转到授权同意页面
238             `autoapprove` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
239             PRIMARY KEY (`client_id`)
240             ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
241         * */
242         return new JdbcClientDetailsService(dataSource);
243     }
244 }三、授权中心配置
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {/*** 属性描述:认证服务器加载用户信息对象** @date : 2020/4/13 0013 上午 12:16*/private final MyUserDetailServiceImpl myUserDetailServiceImpl;/*** 功能描述:授权中心安全配置** @author : XXSD* @date : 2020/10/10 0010 下午 1:11*/public WebSecurityConfig(MyUserDetailServiceImpl myUserDetailServiceImpl) {this.myUserDetailServiceImpl = myUserDetailServiceImpl;}/*** 功能描述:用于构建用户认证组件,需要传递userDetailsService和密码加密器** @author : XXSD* @date : 2020/4/13 0013 上午 12:15*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailServiceImpl).passwordEncoder(passwordEncoder());}/*** 功能描述:配置安全拦截策略** @author : XXSD* @date : 2021/1/9 0009 下午 6:34*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭CSRF跨域检查.csrf().disable()
//                .authorizeRequests()
//                //配置其他请求要求登录
//                .anyRequest().authenticated()
//                //设置并行策略
//                .and()
//                // 可以从默认的login页面登录
//                .formLogin();}/*** 设置前台静态资源不拦截*/@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**");}/*** 功能描述:随机密码加密器** @author : XXSD* @date : 2020/4/13 0013 上午 12:19*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}}
相关文章:
微服务下的SpringSecurity认证端
从三板斧开始微服务下的SpringSecurity开始 一、引入组件包 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> 二、创建适配器 AuthorizationServerConfig…...
 
苹果电脑菜单栏应用管理软件Bartender 4 mac软件特点
Bartender mac是一款可以帮助用户更好地管理和组织菜单栏图标的 macOS 软件。它允许用户隐藏和重新排列菜单栏图标,从而减少混乱和杂乱。 Bartender mac软件特点 菜单栏图标隐藏:Bartender 允许用户隐藏菜单栏图标,只在需要时显示。这样可以…...
笙默考试管理系统-MyExamTest----codemirror(65)
笙默考试管理系统-MyExamTest----codemirror(65) 目录 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试管理系统-MyExamTest----codemirror 四、 笙默考试管理系统-MyExamTest---…...
 
git在本地创建dev分支并和远程的dev分支关联起来
文章目录 git在本地创建dev分支并和远程的dev分支关联起来1. 使用git命令2. 使用idea2.1 先删除上面建的本地分支dev2.2 通过idea建dev分支并和远程dev分支关联 3. 查看本地分支和远程分支的关系 git在本地创建dev分支并和远程的dev分支关联起来 1. 使用git命令 git checkout…...
 
【C++】深入了解构造函数之初始化列表
目录 一、再谈构造函数 1、引入 1)构造函数体赋值 2)不同成员变量赋值 2、初始化列表 一、再谈构造函数 1、引入 1)构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值…...
差分--差分数组快速计算L到R值相加后的数组
目录 差分:思路代码: 原题链接 差分: 输入一个长度为 n 的整数序列。 接下来输入 m 个操作,每个操作包含三个整数 l,r,c ,表示将序列中 [l,r] 之间的每个数加上 c 。 请你输出进行完所有操作后的序列。 输入格式 第…...
 
《NLP入门到精通》栏目导读(01/2)
一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》,因此,读者需要一定得深度学习基础,才能过度到此栏目内容。 二、博客建设理念 本博客基地,将建成人工智能领域的参考资料库;…...
 
three.js实现电子围栏效果(纹理贴图)
three.js实现电子围栏效果(纹理贴图) 实现步骤 围栏的坐标坐标转换为几何体顶点,uv顶点坐标加载贴图,移动 图例 代码 <template><div class"app"><div ref"canvesRef" class"canvas-…...
 
DHSP和DNS
一、服务程序 1.1DHCP定义 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下,DHCP作为Windows Server的一个服务组…...
 
Python冒号的解释
1. “没什么首次没有为第二个,跳了三个”。它得到的切片序列的每一个第三个项目。 扩展片是你想要的。新在Python 2.3 2. Python的序列切片地址可以写成[开始:结束:一步]和任何启动,停止或结束可以被丢弃。a[::3]是每第三个序列。…...
 
uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端鉴权拦截器实现
锋哥原创的uniapp微信小程序投票系统实战: uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…...
 
固乔快递查询助手:批量、快速、全面的快递信息查询软件
在快递行业飞速发展的今天,如何高效、准确地掌握快递信息成为了很多人的需求。而固乔快递查询助手正是解决这一难题的利器。 固乔快递查询助手是一款专注于快递信息查询的软件,支持多家主流快递公司查询。用户只需输入单号,即可快速查询到实时…...
 
C#,归并排序算法(Merge Sort Algorithm)的源代码及数据可视化
归并排序 归并算法采用非常经典的分治策略,每次把序列分成n/2的长度,将问题分解成小问题,由复杂变简单。 因为使用了递归算法,不能用于大数据的排序。 核心代码: using System; using System.Text; using System.Co…...
 
Linux的网络服务DHCP
一.了解DHCP服务 1.1 DHCP定义 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下,DHCP作为Windows Server的一个服…...
 
【小沐学CAD】开源Assimp库导入三维模型(C++、Python)
文章目录 1、简介2、下载编译3、代码测试3.1 C3.2 pyassimp(Python) 结语 1、简介 https://github.com/assimp/assimp Open Asset Import Library 是一个库,用于将各种 3D 文件格式加载为共享的内存格式。它支持 40 多种用于导入的文件格式和…...
 
RT-Thread:SPI万能驱动 SFUD 驱动Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动
关键词:SFUD,FLASH,W25Q64,W25Q128,STM32F407 说明:RT-Thread 系统 使用 SPI万能驱动 SFUD 驱动 Flash W25Q64,通过 STM32CubeMX 配置 STM32 SPI 驱动。 提示:SFUD添加后的存储位置 1.打开RT-Thread Sett…...
 
Python学习笔记-使用Anaconda+VSCode配置开发环境
文章目录 概述一、安装Anaconda1.1 下载软件1.2 安装anaconda1.3 配置环境 二、配置虚拟环境2.1 使用conda创建一个新的虚拟环境2.1.1 使用search指令查看支持的python的版本:2.1.2 使用create创建指定版本的虚拟环境:2.1.3 使用env list查看虚拟环境列表…...
RabbitMQ的关键概念解析
RabbitMQ 是一个广泛使用的开源消息代理,它允许应用程序通过复杂的路由和存储机制来交换数据。理解 RabbitMQ 的核心概念对于有效地使用它至关重要。以下是 RabbitMQ 的一些关键概念及其工作流程: 关键概念 生产者(Producer) 生产…...
Python快速排序
快速排序是一种常用的排序算法,它通过递归地将数组分割成较小的子数组,然后对这些子数组进行排序,最终将它们合并成一个有序的数组。具体步骤如下: 1. 选择一个基准元素,通常是数组中的第一个元素。 2. 将数组分成两部…...
 
SpringBoot整合人大金仓数据库KingBase
1 去KingBase官网下载驱动jar包 2 将解压得到的所有jar包放置在libs目录下(没有就新建一个目录) 3 在pom文件添加相关依赖 <!--添加KingBase所需要的依赖--> <dependency><groupId>com.kingbase</groupId><artifactId>kin…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
 
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
 
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
 
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
 
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
 
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
