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

spring security OAuth2 搭建资源服务器以及授权服务器/jdbc/jwt两种方案

一、认证服务器基于jdbc方式

如果不懂请移步上一篇文章:Spring security OAuth2 授权服务器搭建-CSDN博客

    在上一篇文章中,TokenStore的默认实现为 InHenoryTokenStore 即内存存储,对于 CLient 信息,userDetaitsServce 接负责从存储库中读取数据,在上面的案例中默认使用的也是 InHemoryCLientDetalsService 实现类。如果要想使用政据库存储,只要提供这些接口的实现类即可,而框架已经为我们写好 dbekenStore 和 dbcclientDetatsService

1.1 数据库所需表

我们使用spring security 自带的sql 语句生成对应的表结构,我们关注一下 oauth_client_details  这个表,这个表用来储存用户密钥信息,相当于前面的这个地方

clients.inMemory() //基于内存,后期可以入库查出来.withClient("client-lq").secret(passwordEncoder.encode("secret-lq"))

-- 写入客户端信息
INSERT INTO oauth_client_details
VALUES ('client-id', NULL,'$2a$10$2McX6ml8CVK3RUNpLkX1zeQeNkrEvLCPOJ2hhpG18XMeIMbJWIJnK', 'read', 'authorization_code,refresh_token','http://www.baidu.com',NULL, NULL, NULL, NULL,NULL);

client_secret 需要加密存进去,否则会报不成功

--  structure for clientdetailsDROP TABLE IF EXISTS `clientdetails`;
CREATE TABLE clientdetails (appId                  varchar(256) NOT NULL,resourceIds            varchar(256)  DEFAULT NULL,appSecret              varchar(256)  DEFAULT NULL,scope                  varchar(256)  DEFAULT NULL,grantTypes             varchar(256)  DEFAULT NULL,redirectUrl            varchar(256)  DEFAULT NULL,authorities            varchar(256)  DEFAULT NULL,access_token_validity  int(11)       DEFAULT NULL,refresh_token_validity int(11)       DEFAULT NULL,additionalInformation  varchar(4096) DEFAULT NULL,autoApproveScopes      varchar(256)  DEFAULT NULL,PRIMARY KEY (appId)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- Table structure for oauth_access_token
DROP TABLE IF EXISTS oauth_access_token;
CREATE TABLE oauth_access_token  (token_id varchar(256) DEFAULT NULL,token blob,authentication_id varchar(256) NOT NULL,user_name     varchar(256) DEFAULT NULL,client_id     varchar(256) DEFAULT NULL,authentication blob ,refresh_token  varchar(256) DEFAULT NULL,PRIMARY KEY (authentication_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;--  Table structure for oauth_approvalsDROP TABLE IF EXISTS  oauth_approvals;
CREATE TABLE oauth_approvals (userId varchar(256) DEFAULT NULL,clientId varchar(256) DEFAULT NULL,scope varchar(256) DEFAULT NULL,status varchar(10) DEFAULT NULL,expiresAt timestamp NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,lastModifiedAt date null
)ENGINE=InnODB DEFAULT CHARSET=utf8mb4;-- Table structure for oauth_client_details
DROP TABLE IF EXISTS oauth_client_details;
CREATE TABLE oauth_client_details (client_id               varchar(256) NOT NULL,resource_ids            varchar(256)  DEFAULT NULL,client_secret           varchar(256)  DEFAULT NULL,scope                   varchar(256)  DEFAULT NULL,authorized_grant_types  varchar(256)  DEFAULT NULL,web_server_redirect_uri varchar(256)  DEFAULT NULL,authorities             varchar(256)  DEFAULT NULL,access_token_validity   int(11)       DEFAULT NULL,refresh_token_validity  int(11)       DEFAULT NULL,additional_information  varchar(4096) DEFAULT NULL,autoapprove             varchar(256)  DEFAULT NULL,PRIMARY KEY (client_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;--  Table structure for oauth_clienttoken
DROP TABLE IF EXISTS  oauth_client_token;
CREATE TABLE oauth_client_token (token_id          varchar(256) DEFAULT NULL,token             blob,authentication_id varchar(256) NOT NULL,user_nam          varchar(256) DEFAULT NULL,client_id         varchar(256) DEFAULT NULL,PRIMARY KEY (authentication_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;--  Table structure for oauth_code
DROP TABLE IF EXISTS oauth_code;
CREATE TABLE oauth_code (code           varchar(256) DEFAULT NULL,authentication blob
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- Table structure for oauth_refresh_token
DROP TABLE IF EXISTS  oauth_refresh_token;
CREATE TABLE oauth_refresh_token (
token_id varchar(256) DEFAULT NULL,
token blob,
authentication blob
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;select * from  oauth_refresh_token;-- 写入客户端信息
INSERT INTO oauth_client_details
VALUES ('client-id', NULL,'$2a$10$2McX6ml8CVK3RUNpLkX1zeQeNkrEvLCPOJ2hhpG18XMeIMbJWIJnK', 'read', 'authorization_code,refresh_token','http://www.baidu.com',NULL, NULL, NULL, NULL,NULL);

1.2 认证服务器配置

@Configuration
@EnableAuthorizationServer  //指定当前应用为授权服务器
public class JdbcAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {private final PasswordEncoder passwordEncoder;private final UserDetailsService userDetailsService;private final AuthenticationManager authenticationManager;private final DataSource dataSource;@Autowiredpublic JdbcAuthorizationServerConfig(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService, AuthenticationManager authenticationManager, DataSource dataSource) {this.passwordEncoder = passwordEncoder;this.userDetailsService = userDetailsService;this.authenticationManager = authenticationManager;this.dataSource = dataSource;}@Beanpublic ClientDetailsService clientDetails() {JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);// 使用哪一种加密方式clientDetailsService.setPasswordEncoder(passwordEncoder);return clientDetailsService;}// 用来配置授权服务器可以为哪些客户端授权   client_id,secret  redirect_url@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(clientDetails());// 使用jdbc存储}@Beanpublic TokenStore tokenStore() {JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);return jdbcTokenStore;}// 配置令牌存储@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.tokenStore(tokenStore());// 配置令牌存储为数据库存储endpoints.userDetailsService(userDetailsService);// 配置 tokenServices 参数DefaultTokenServices tokenServices = new DefaultTokenServices();//修改默认令牌生成服务tokenServices.setTokenStore(endpoints.getTokenStore());// 基于数据库令牌生成tokenServices.setSupportRefreshToken(true);//是否支持刷新令牌tokenServices.setReuseRefreshToken(true); // 是否重复使用刷新令牌( 直到过期tokenServices.setClientDetailsService(endpoints.getClientDetailsService());//设置客户端信息tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());//用来控制令牌存储增强策略// 访问令牌的默认有效期( 以秒为单位)。过期的令牌为零或负数。tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30)); // 30天endpoints.tokenServices(tokenServices);// 使用配置令牌服务}}

1.3 security 配置

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();inMemoryUserDetailsManager.createUser(User.withUsername("root").password(passwordEncoder().encode("123456")).roles("ADMIN").build());return inMemoryUserDetailsManager;}@Override@Beanprotected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 开启表单登录.and().csrf().disable();}
}

1.4 数据库配置

@Configuration
@Slf4j
public class MysqlDsConfig {/***  配置数据源* @return*/@Primary@Beanpublic DataSource mysqlDataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/oauth3");dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUsername("root");dataSource.setPassword("12345678");return dataSource;}}

1.5 启动测试

当我们刷新token的时候 oauth_refresh_token 会有值进去,使用 apifox 测试令牌


二、资源服务器基于 jdbc 方式

需要连接数据库信息,跟认证服务器数据源一样,因为资源服务器最终也要去读取表信息

所需的依赖,资料参考 哔哩博主,不良人编程 

<properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-cloud.version>Hoxton.SR9</spring-cloud.version><spring-boot.version>2.3.7.RELEASE</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-resource-server</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- 数据源支持 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

2.1  资源服务器配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {private final DataSource dataSource;@Autowiredpublic ResourceServerConfig(DataSource dataSource) {this.dataSource = dataSource;}@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.tokenStore(tokenStore());}public TokenStore tokenStore() {return new JdbcTokenStore(dataSource);}
}

2.2 测试controller

@RestController
public class HelloController {@RequestMapping("hello")public String hello() {System.out.println("hello resource server ");return "hello resource server";}
}

2.3 测试结果

当我们这个时候访问的时候就需要带上 Authorization:Bearer   参数,否则提示 Full authentication is required to access this resource 

curl -H "Authorization:Bearer token 对应的值" http://127.0.0.1:8083/hello


三、认证服务器基于 jwt 方式

jwt 分为三部分,用三个点隔开  ,第一部分标识 header 标识用那种加密方式;中间部分为subject 主体信息,可以是用户信息,也可以是一个json数据;最后一部分为sign 签名信息,这个信息需要设置足够复杂才能被破解;

3.1 认证服务器配置

可能在疑问,为什么还是要用数据库,这次我们只需要从库里面读取一次用户信息,只是使用一张表 oauth_client_details 其他信息都不会使用,jwt 有自动过期时间

@Configuration
@EnableAuthorizationServer  //指定当前应用为授权服务器
public class JwtAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {private final PasswordEncoder passwordEncoder;private final UserDetailsService userDetailsService;private final AuthenticationManager authenticationManager;private final DataSource dataSource;@Autowiredpublic JwtAuthorizationServerConfig(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService, AuthenticationManager authenticationManager, DataSource dataSource) {this.passwordEncoder = passwordEncoder;this.userDetailsService = userDetailsService;this.authenticationManager = authenticationManager;this.dataSource = dataSource;}@Beanpublic ClientDetailsService clientDetails() {JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);// 使用哪一种加密方式clientDetailsService.setPasswordEncoder(passwordEncoder);return clientDetailsService;}// 用来配置授权服务器可以为哪些客户端授权   client_id,secret  redirect_url@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(clientDetails());// 使用jdbc存储}// 使用同一个秘钥编码@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();jwtAccessTokenConverter.setSigningKey("12332111");return jwtAccessTokenConverter;}// jwt生成方式生成令牌@Beanpublic TokenStore tokenStore() {JwtTokenStore jdbcTokenStore = new JwtTokenStore(jwtAccessTokenConverter());return jdbcTokenStore;}// 配置令牌存储@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.tokenStore(tokenStore())// 配置jwt令牌存储为数据库存储.accessTokenConverter(jwtAccessTokenConverter());}//http://127.0.0.1:8082/oauth/authorize?client_id=client&response_type=code&redirect_url=https://www.baidu.com}

3.2 测试效果

1、页面授权效果有所不同,获取code

2、返回的令牌有所不同

api fox 效果

四、资源服务器基于 jwt 方式

    我们只需要跟认证服务器加密规则设置相同即可,因为jwt 自带加密算法,就类似于我们两个定义了一套rsa的秘钥,我们加密规则相同,约定一个签名戳,这个别人获取不到,你请求过来的时候我验证合法性,所以就不需要用到数据库了

4.1 资源服务器配置

@Configuration
@EnableResourceServer
public class JwtResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.tokenStore(tokenStore());}// jwt生成方式生成令牌@Beanpublic TokenStore tokenStore() {JwtTokenStore jdbcTokenStore = new JwtTokenStore(jwtAccessTokenConverter());return jdbcTokenStore;}// 使用同一个秘钥编码@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();jwtAccessTokenConverter.setSigningKey("12332111");return jwtAccessTokenConverter;}
}

4.2 测试效果

curl -H "Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjYzMTY1MTAsInVzZXJfbmFtZ
SI6InJvb3QiLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjEyYTgyMmNhLWQ3MTgtNDE1Yy1hYWQ3LTA5ZjIxODNjNzY0YiIsImNsaWVudF9pZCI6ImNsaWVudC1scSIsInNjb3BlI
jpbInJlYWQ6dXNlciJdfQ.myzFE0VJOhlFLOsddBknOeB6Y499RwZ1X2zTM4PxC00" http://127.0.0.1:8083/hello
 

Z1X2zTM4PxC00" http://127.0.0.1:8083/hello
hello resource server
D:\java-tool\idea-project\spring-security-study>
 

使用apifox 测试

相关文章:

spring security OAuth2 搭建资源服务器以及授权服务器/jdbc/jwt两种方案

一、认证服务器基于jdbc方式 如果不懂请移步上一篇文章&#xff1a;Spring security OAuth2 授权服务器搭建-CSDN博客 在上一篇文章中&#xff0c;TokenStore的默认实现为 InHenoryTokenStore 即内存存储&#xff0c;对于 CLient 信息&#xff0c;userDetaitsServce 接负责从存…...

计算机视觉—3d点云数据基础

点云数据 3d点云数据由来 3d点云 3D Point Cloud是一种用于表示三维空间中对象或场景的数据结构。在最基础的形式中&#xff0c;它是一个包含多个三维坐标点&#xff08;X, Y, Z&#xff09;的集合。这些点是通过对实际物体或场景表面进行离散采样而获得的&#xff0c;因此&a…...

Matlab simulink建模与仿真 第十八章(Stateflow状态机)

参考视频&#xff1a;Simulink/stateflow的入门培训_哔哩哔哩_bilibili 一、概述 Stateflow是集成于Simulink中的图形化设计与开发工具&#xff0c;主要用于针对控制系统中的复杂控制逻辑进行建模与仿真&#xff0c;或者说&#xff0c;Stateflow适用于针对事件响应系统进行建模…...

Linux系统终端中文件权限的10位字符是什么意思

Linux操作系统终端长格式显示的文件 在Linux操作系统终端中用文件长格式命令ls -l显示文件&#xff0c;如上图。第一列10个字符表示的含义如下&#xff1a; drwxrwxrwx 第一个字符是表示该文件的类型&#xff0c;如红色d表示该文件是一个目录&#xff0c;详细内容可以参考我…...

Qt QSerialPort串口编程

文章目录 Qt QSerialPort串口编程Qt Serial Port模块简述1.QSerialPortInfo类1.1示例用法 2.QSerialPort类2.1设置串口参数2.2打开串口2.3数据读写2.4关闭串口 3.串口编程基本流程3.1 简单实例 Qt QSerialPort串口编程 Qt 框架的Qt Serial Port 模块提供了访问串口的基本功能&…...

扫雷游戏及其中的知识点

大家好呀,今天我们给大家讲解扫雷游戏如何用C语言制作,以及制作扫雷游戏中的一些C语言知识。 想到扫雷游戏,大家有什么想法吗?大家还记得扫雷游戏是什么样子的吗?我在网上找了一些扫雷游戏的图片给大家提供参考: 如图所示,扫雷游戏需要的元素有以下几个: 1.进入游戏界面…...

【乐企-业务篇】开票前置校验服务-规则链服务接口实现(发票基础信息校验)

开票前置校验服务-规则链服务接口实现(发票基础信息校验) 代码 import liquibase.pro.packaged.L; import org.apache.commons.collections4.Collec...

【搜索算法】以扩召回为目标,item-tag不如query-tag能扩更多数量

首先ElasticSearch的召回结果已大量解决了精确召回的问题&#xff0c;扩召回主要就是增加一些推荐的搜索结果。 以item类目tag为例&#xff0c; 如果item类目体系一共20个类目&#xff0c;每个item都有一个类目&#xff0c;一共有10000个item&#xff0c;则平均每个类目tag下有…...

SpringBoot入门(黑马)

1. SpringBootWeb入门开发 需求&#xff1a;使用SpringBoot 开发一个web 应用&#xff0c;浏览器发起请求 /hello 后&#xff0c;给浏览器返回字符串"Hello World~"。 步骤&#xff1a; 1. 创建springBoot工程&#xff0c;并勾选web开发相关依赖。 2. 定义 HelloCo…...

Stream流操作

准备工作 准备 Gender 枚举类以及 Customer 类 enum Gender {MALE("男性"), FEMALE("女性");private String value;Gender() {}Gender(String value) {this.value value;}Overridepublic String toString() {return "Gender{" "value&qu…...

【Linux】查看操作系统开机时初始化的驱动模块列表的一个方法

这个方法是摸索出来的&#xff0c;也不一定对&#xff1a; 1、驱动层module_init(module_init_function)作为模块初始化&#xff0c;并且提供模块内部初始化的函数名&#xff1b; 2、找到所有驱动目录drivers下所有module_init(module_init_function)&#xff0c;在内核6.9.0…...

快速入门Vue

Vue是什么 Vue.js&#xff08;通常简称为Vue&#xff09;是一个开源的JavaScript框架&#xff0c;用于构建用户界面和单页应用程序&#xff08;SPA&#xff09;。它由尤雨溪&#xff08;Evan You&#xff09;在2014年开发并发布。Vue的核心库只关注视图层&#xff0c;易于上手…...

ubuntu系统服务器离线安装python包

一、根据工程需要本地下载所需python包 1. 下载环境requirements.txt pip freeze > requirements.txt2. 根据requirements.txt下载python包 注意&#xff1a;查看服务器属于x_86架构还是arm架构、cpython还是pypy 2.1 确定服务器架构&#xff08;终端输入&#xff09; …...

re题(30)BUUCTF-[HDCTF2019]Maze

BUUCTF在线评测 (buuoj.cn) 查一下壳&#xff0c;32位upx壳 脱完壳放到ida&#xff0c;shiftF12看一下字符串&#xff0c;是个迷宫&#xff0c;maze&#xff08;迷宫&#xff09; 这里有一个经典的花指令 (导致找不到main函数) 下方有个奇怪的jnz指令&#xff0c;它跳转到了下…...

day36+day37 0-1背包

### 9.9 01背包问题&#xff08;一维二维&#xff09; 背包问题分类&#xff1a;01背包&#xff08;一种物品只有一个&#xff09;&#xff0c;完全背包&#xff08;一种物品有无数个&#xff09;&#xff0c;多重背包&#xff08;不同物品有不同数量&#xff09; 46. 携带研究…...

PostMan使用变量

环境变量 使用场景 当测试过程中&#xff0c;我们需要对开发环境、测试环境、生产环境进行测试 不同的环境对应着不同的服务器&#xff0c;那么这个时候我们就可以使用环境变量来区分它们 避免切换测试环境后&#xff0c;需要大量的更改接口的url地址 全局变量 使用场景 当…...

多线程同步

多线程 程序中默认只有一个线程&#xff0c;pthread_create()函数调用后就有2个线程。 pthread_create() #include <pthread.h> #include <string.h> #include <unistd.h> #include <iostream> using namespace std; //线程函数 void * callback(vo…...

第159天:安全开发-Python-协议库爆破FTPSSHRedisSMTPMYSQL等

案例一: Python-文件传输爆破-ftplib 库操作 ftp 协议 开一个ftp 利用ftp正确登录与失败登录都会有不同的回显 使用ftplib库进行测试 from ftplib import FTP # FTP服务器地址 ftp_server 192.168.172.132 # FTP服务器端口&#xff08;默认为21&#xff09; ftp_po…...

软件测试 | APP测试 —— Appium 的环境搭建及工具安装教程

大家应该都有同一种感觉&#xff0c;学习appium最大的难处之一在于环境的安装&#xff0c;安装流程比较繁琐&#xff0c;安装的工具和步骤也较多&#xff0c;以下是基于Windows系统下的Android手机端的安装流程。就像我们在用Selenium进行web自动化测试的时候一样&#xff0c;我…...

计算机人工智能前沿进展-大语言模型方向-2024-09-13

计算机人工智能前沿进展-大语言模型方向-2024-09-13 1. OneEdit: A Neural-Symbolic Collaboratively Knowledge Editing System Authors: Ningyu Zhang, Zekun Xi, Yujie Luo, Peng Wang, Bozhong Tian, Yunzhi Yao, Jintian Zhang, Shumin Deng, Mengshu Sun, Lei Liang, Z…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

基于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…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

python读取SQLite表个并生成pdf文件

代码用于创建含50列的SQLite数据库并插入500行随机浮点数据&#xff0c;随后读取数据&#xff0c;通过ReportLab生成横向PDF表格&#xff0c;包含格式化&#xff08;两位小数&#xff09;及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...