Spring Security学习

系列文章目录

第一章 基础知识、数据类型学习
第二章 万年历项目
第三章 代码逻辑训练习题
第四章 方法、数组学习
第五章 图书管理系统项目
第六章 面向对象编程:封装、继承、多态学习
第七章 封装继承多态习题
第八章 常用类、包装类、异常处理机制学习
第九章 集合学习
第十章 IO流、多线程学习
第十一章 仓库管理系统JavaSE项目
第十二章 员工管理系统、多表查询、反射实现DBHelper学习
第十三章 DML、DDL、数据库对象学习
第十四章 网络编程、各种标签、CSS学习
第十五章 ECMAScript、BOM学习
第十六章 DOM、jQuery学习
第十七章 servlet、jsp、Cookie、Ajax学习
第十八章 融资管理系统JavaWeb项目
第十九章 MyBatis框架学习
第二十章 逆向工程、Spring框架IOC、AOP学习
第二十一章 SpringMVC框架学习
第二十二章 SpringBoot框架学习
第二十三章 招聘网站框架项目
第二十四章 Vue介绍、窗体内操作、窗体间操作学习
第二十六章 Vue路由配置、网络请求访问框架项目、element组件介绍学习
第二十五章 标准管理系统Vue项目
第二十六章 Linux安装、Nginx反向代理、负载均衡学习
第二十七章 Docker学习
第二十八章 Jenkins学习
第二十九章 Nexus学习
第三十章 Spring Security学习


文章目录

  • 系列文章目录
  • 前言
  • 一、Spring Security介绍
    • 1. Spring Security介绍
    • 2. Spring Security特性
  • 二、Spring Security代码编写:第一阶段
    • 1. 创建Maven项目
    • 2. 在pom文件里添加依赖
    • 3. 目录结构
    • 4. SecurityController文件
    • 5. 配置SpringBootMain文件
    • 6. application.yml文件
    • 7. main.html文件
    • 8. 启动项目
  • 三、Spring Security代码编写:第二阶段
    • 1. 第二阶段第三阶段总体结构图
    • 2. SecurityConfig文件
    • 3. UserDetailsServiceImpl文件
    • 4. login.html文件
    • 5. 实现效果
  • 四、Spring Security代码编写:第三阶段
    • 1. RememberMeConfig文件
    • 2. SecurityConfig文件
    • 3. login.html更改
    • 4. 创建数据库和表
    • 5. 实现效果
  • 五、Spring Security代码编写:第四阶段
    • 1. 项目结构
    • 2. 新增show.html界面
    • 3. 更新UserDetailsServiceImpl文件返回值
    • 4. 实现效果
  • 六、CSRF
  • 总结


前言

本文我们要讲述:
Spring Security
在下攸攸太上,是有人类女友的外星来客。


一、Spring Security介绍

1. Spring Security介绍

Spring Security是一个功能强大且灵活的安全框架,用于在Spring应用程序中提供身份验证授权、保护和攻击防护等安全功能。它提供了大量的配置选项和扩展机制,使开发者能够轻松地集成和定制应用程序的安全需求。

2. Spring Security特性

身份验证(Authentication):Spring Security提供了多种身份验证机制,包括基于表单、HTTP基本认证、OpenID、LDAP、OAuth等。它还支持自定义身份验证逻辑,可以轻松地集成其他身份验证提供者。

授权(Authorization):Spring Security提供了强大的授权机制,可以根据用户的身份和角色来限制其对资源的访问。它支持基于角色和权限的访问控制,可以在代码和配置中定义细粒度的安全规则。

攻击防护(Attack Protection):Spring Security提供了多种防护机制,用于防范常见的安全威胁,如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、点击劫持、会话管理等。它使用了各种技术和策略,如CSRF令牌、XSS过滤器、会话管理器等来保护应用程序的安全性。

安全事件和日志(Security Events and Logging):Spring Security提供了丰富的安全事件和日志功能,可以记录和跟踪与安全相关的事件。开发者可以基于这些事件和日志来监控和审计应用程序的安全性,并对可能的安全威胁做出响应。

扩展性和定制化(Extensibility and Customization):Spring Security提供了灵活的配置选项和扩展机制,使开发者能够根据应用程序的特定需求进行定制。开发者可以编写自定义的认证和授权逻辑,实现自定义的安全过滤器和拦截器,以满足应用程序的特定安全需求。

本文将着重介绍身份验证、授权的特性。

二、Spring Security代码编写:第一阶段

1. 创建Maven项目

在这里插入图片描述

2. 在pom文件里添加依赖

    <dependencies><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity5</artifactId><version>3.0.4.RELEASE</version></dependency><!-- 4.添加mysql数据库的驱动包依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!-- 3.添加Mybatis 的启动器依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency><!-- SpringBoot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.10.RELEASE</version><type>pom</type><scope>import</scope></dependency><!-- SpringMVC --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.10.RELEASE</version></dependency><!-- Thymeleaf --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.1.10.RELEASE</version></dependency><!--Spring Security--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId><version>2.1.10.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>compile</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.7.0</version></dependency><!--json--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.60</version><scope>compile</scope></dependency></dependencies>

3. 目录结构

在这里插入图片描述

4. SecurityController文件

@Controller
public class SecurityController {@RequestMapping("/main")public String main(){return "main";}
}

5. 配置SpringBootMain文件

@SpringBootApplication
public class SpringBootMain {public static void main(String[] args) {SpringApplication.run(SpringBootMain.class, args);}
}

6. application.yml文件

server:port: 8181spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword:url: jdbc:mysql://localhost:3308/security

7. main.html文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>main</title>
</head>
<body><h1>我是Main页面!我要刺杀老师!喝啊!</h1><a href="/logout">退出登录</a>
</body>
</html>

8. 启动项目

打开网页,输入:127.0.0.1:8080
做一次页面点击后,控制台输出密码
在这里插入图片描述
我们输入固定的用户名:user与密码:891de0f8-256c-4f74-ba5b-999f25531c82可进行登录,登录后在地址栏可以访问/main页面
在这里插入图片描述
在这里插入图片描述
没有登录前,会自动跳转到/login页面,因为没有做登录之前,程序不让进行其他操作(第二阶段可改)
我们其实登录都是使用自定义的用户名和密码,于是乎,我们如何自定义用户名、密码呢?且听下回分解

三、Spring Security代码编写:第二阶段

欸!我就是下回诶!

1. 第二阶段第三阶段总体结构图

在这里插入图片描述

2. SecurityConfig文件

package com.jjy.config;import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {// 表单认证http.formLogin().loginProcessingUrl("/login")//此处表单不写action属性也可以  //当发现/login时认为是登录,需要执行UserDetailsServiceImpl.successForwardUrl("/main")   //此处是post请求.loginPage("/login.html");// url 拦截http.authorizeRequests().antMatchers("/login.html").permitAll() //login.html不需要被认证.anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。//关闭csrf防护http.csrf().disable();}@Bean // 是Bean标签,security框架要求密码必须是加密的处理,public PasswordEncoder getPwdEncoder(){return new BCryptPasswordEncoder();}
}

3. UserDetailsServiceImpl文件

自定义用户名为admin,密码为123

package com.jjy.service.impl;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 1. 查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundExceptionif (!username.equals("admin")){throw new UsernameNotFoundException("用户名不存在");}// 把查询出来的密码进行解析,或者直接把password放到构造方法中String password = passwordEncoder.encode("123");return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));}
}

4. login.html文件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/login" method="post">用户名:<input type="text" name="username"><br/>密码:<input type="password" name="password"><br/><input type="submit" value="提交">
</form>
</body>
</html>

5. 实现效果

在这里插入图片描述

四、Spring Security代码编写:第三阶段

记忆功能实现

1. RememberMeConfig文件

package com.jjy.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
@Configuration
public class RememberMeConfig {@Autowiredprivate DataSource dataSource;@Beanpublic PersistentTokenRepository getPersistentTokenRepository() {JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl=new JdbcTokenRepositoryImpl();jdbcTokenRepositoryImpl.setDataSource(dataSource);//自动建表,第一次启动时需要,第二次启动时注释掉//jdbcTokenRepositoryImpl.setCreateTableOnStartup(true);  //该代码不好用,使用sql手动创建库,表return jdbcTokenRepositoryImpl;}
}

2. SecurityConfig文件

package com.jjy.config;import com.jjy.service.impl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredPersistentTokenRepository repository;// private  RememberMeConfig repository;@Autowiredprivate UserDetailsServiceImpl userDetailsService;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.rememberMe().userDetailsService(userDetailsService) //登录逻辑交给哪个对象.tokenRepository(repository);   //持久层对象// 表单认证http.formLogin().loginProcessingUrl("/login")//此处表单不写action属性也可以  //当发现/login时认为是登录,需要执行UserDetailsServiceImpl.successForwardUrl("/main")   //此处是post请求.loginPage("/login.html");// url 拦截http.authorizeRequests().antMatchers("/login.html").permitAll() //login.html不需要被认证.anyRequest().authenticated();//所有的请求都必须被认证。必须登录后才能访问。//关闭csrf防护http.csrf().disable();}@Bean // 是Bean标签,security框架要求密码必须是加密的处理,public PasswordEncoder getPwdEncoder(){return new BCryptPasswordEncoder();}
}

3. login.html更改

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="/login" method="post">用户名:<input type="text" name="username"><br/>密码:<input type="password" name="password"><br/><input type="checkbox" name="remember-me" value="true"/>记住我 <br/><input type="submit" value="提交">
</form>
</body>
</html>

4. 创建数据库和表

创建security数据库
创建表的语句

create table persistent_logins (
username varchar(64) not null, 
series varchar(64) primary key, 
token varchar(64) not null, 
last_used timestamp not null)

5. 实现效果

输入如下属性,点击记住我(密码123),之后提交
在这里插入图片描述
可以自动跳转页面,同时数据库新增一条数据
在这里插入图片描述
点击退出登录后,数据库内数据被清除
在这里插入图片描述

五、Spring Security代码编写:第四阶段

本阶段主要做权限验证

1. 项目结构

在这里插入图片描述

2. 新增show.html界面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>获得springsequraty属性</h1>
用户名:<span sec:authentication="name">123</span><br/>
用户名:<span sec:authentication="principal.username">456</span><br/>
凭证:<span sec:authentication="credentials">456</span><br/>
权限和角色:<span sec:authentication="authorities">456</span><br/>
客户端地址:<span sec:authentication="details.remoteAddress">456</span><br/>
sessionId:<span sec:authentication="details.sessionId">456</span><br/>通过权限判断:
<button sec:authorize="hasAuthority('/insert')">新增</button>
<button sec:authorize="hasAuthority('/delete')">删除</button>
<button sec:authorize="hasAuthority('/update')">修改</button>
<button sec:authorize="hasAuthority('/select')">查看</button>
<br/>
通过角色判断:
<button sec:authorize="hasRole('abc')">新增</button>
<button sec:authorize="hasRole('abc')">删除</button>
<button sec:authorize="hasRole('abc')">修改</button>
<button sec:authorize="hasRole('abc1')">查看</button>
</body>
</html>

3. 更新UserDetailsServiceImpl文件返回值

	return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,/select,/insert,ROLE_abc1"));

在这里插入图片描述
赋予admin用户select、insert的权限,归于ROLE_abc1组下

4. 实现效果

登录后,我们通过地址栏输入http://127.0.0.1:8181/show进入show页面,可以发现,用户admin的权限只有新增、查看两项。
在这里插入图片描述

六、CSRF

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击技术,攻击者通过伪造用户的请求来实现非法操作,利用用户在目标网站上的身份和权限。

CSRF攻击通常发生在存在用户身份验证的应用程序中。攻击者诱使受害者在已经登录过的网站上执行恶意操作,从而利用受害者的权限进行非法操作。攻击者可以通过各种手段,如发送伪造的电子邮件、社交工程攻击、恶意广告等来引诱受害者点击恶意链接或访问恶意网站。

Spring Security是一个功能强大的安全框架,提供了多种功能来保护应用程序免受常见的安全威胁,包括 CSRF攻击。在Spring Security中,默认情况下启用了CSRF防护。

CSRF防护是通过生成和验证一个CSRF令牌来实现的。这个令牌通常是一个随机生成的字符串,由服务器在用户访问页面时生成,并将其附加到表单或请求的头部中。在用户提交请求时,服务器会验证请求中的令牌是否与服务器生成的令牌匹配,如果不匹配,服务器将拒绝该请求,防止CSRF攻击的发生。

在Spring Security配置中,可以使用csrf()方法来配置和启用CSRF防护。默认情况下,Spring Security会生成一个CSRF令牌,并将其附加到表单和请求头中。如果需要关闭CSRF防护,可以使用http.csrf().disable()方法来禁用它。

总结起来,CSRF是一种常见的网络攻击技术,Spring Security提供了默认的CSRF防护来保护应用程序免受此类攻击。


总结

本文讲述了:
Spring Security:进行身份验证、授权功能的框架
在下攸攸太上,如果把我的生活拍成电视剧,那将会是《来自行星的高级生命体》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/150062.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】深度卷积神经网络(AlexNet)

在 LeNet 提出后&#xff0c;卷积神经网络在计算机视觉和机器学习领域中很有名气&#xff0c;但并未起到主导作用。 这是因为 LeNet 在更大、更真实的数据集上训练的性能和可行性还有待研究。 事实上&#xff0c;在 20 世纪 90 年代到 2012 年之间的大部分时间里&#xff0c;…

电线杆上电气组件检测系统源码分享

电线杆上电气组件检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comp…

视频怎么制作成二维码?视频轻松生成二维码的3步操作

现在很多人为了能够更快捷的实现视频内容的分享&#xff0c;会通过将视频生成二维码的方式&#xff0c;让其他人可以通过扫描二维码来查看视频内容。这种方式不需要用户存储视频&#xff0c;扫码就能够在设备上查看视频&#xff0c;有利于提升查看视频的便捷性&#xff0c;可以…

【秋招笔试题】多多排序

解法&#xff1a;简单语法题 package com.sky;import java.util.*;public class Test1 {public static void main(String[] args) {Scanner sc new Scanner(System.in);int N sc.nextInt();int M sc.nextInt();List<String> words new ArrayList<>(N);for (in…

关于TrustedInstaller权限

前言 我们在在删除某些文件时会发现权限不够的情况&#xff0c;那是因为自从 Windows Vista 以来&#xff0c;为了提升安全性&#xff0c;微软对于权限的把控越来越紧。为了对抗恶意软件随意修改系统文件&#xff0c;Trustedinstaller 应运而生。 各权限之间的关系 普通人:Us…

C++STL--------string

文章目录 一、STL介绍二、string1、constructor构造函数2、operator[]方括号运算符重载3、iterator迭代器4、reverse_iterator反向迭代器5、size和length6、capacity7、clear8、shrink_to_fit9、at10、push_back11、append 二、auto类型(C11)1、使用2、真正的价值 三、范围for(…

python全栈学习记录(十八)re、os和sys、subprocess

re、os和sys、subprocess 文章目录 re、os和sys、subprocess一、re1.正则字符2.正则表达式的使用3.group的使用4.贪婪匹配与惰性匹配5.其他注意事项 二、os和sys1.os2.sys 三、subprocess 一、re python中的re模块用来使用正则表达式&#xff0c;正则就是用一系列具有特殊含义…

2024 年最新 Protobuf 结构化数据序列化和反序列化详细教程

Protobuf 序列化概述 Protobuf&#xff08;Protocol Buffers&#xff09;是由Google开发的一种语言中立、平台中立、可扩展的序列化结构数据的方法。它用于在不同系统之间高效地交换数据。Protobuf使用定义文件&#xff08;.proto&#xff09;来描述数据结构&#xff0c;并通过…

Pytest测试实战|执行方式

Pytest测试实战 The pytest framework makes it easy to write small, readable tests, and can scale to support complex functional testing for applications and libraries. 这段话很好地阐述了Pytest的设计思想与强大的特性。在之前阐述了Pytest编写测试用例规范与搜索规…

R包:gplots经典热图

加载R包 # install.packages("gplots")library("gplots")数据 mat <- matrix(rnorm(1200), ncol6)画图1 heatmap.2(xmat)画图2 heatmap.2(xmat, ColvFALSE, dendrogram"row",scale"row",col"bluered",trace"non…

828华为云征文 | 解锁企业级邮件服务,在华为云Flexus x实例上部署Mailcow开源方案

前言 华为云Flexus X实例携手Mailcow开源邮件方案&#xff0c;为企业打造了一个既高效又安全的邮件服务解决方案。Flexus X实例的柔性算力与高性能&#xff0c;是这一方案的坚实基石。它提供CPU内存的灵活定义&#xff0c;以经济型价格实现旗舰级性能&#xff0c;确保邮件服务的…

大模型分布式训练并行技术(一)-概述

近年来&#xff0c;随着Transformer、MOE架构的提出&#xff0c;使得深度学习模型轻松突破上万亿规模参数&#xff0c;传统的单机单卡模式已经无法满足超大模型进行训练的要求。因此&#xff0c;我们需要基于单机多卡、甚至是多机多卡进行分布式大模型的训练。 而利用AI集群&a…

Gitee基本指令操作

目录 1.概念 2. git的基本指令 3. .gitignore 文件 4 . Linux git || gitee || github 1.概念 Git是一种版本控制的软件。 Git是免费且开源的。 Git常被称为 去中心化的分布式的 数据存储。 【其实git也可以进行本地版本控制。对于git&#xff0c;可理解为是一个 本地版本…

超轻量级电竞体验,还有8K超高回报率,雷柏VT1 Air MAX上手

PC玩家想要获得更精彩的游戏体验&#xff0c;除了要关注主机上显卡、CPU等方面的配置&#xff0c;还需要键、鼠标的操控体验跟得上节奏&#xff0c;而在这方面&#xff0c;国产品牌雷柏算是行业里的翘楚&#xff0c;尤其是这两年&#xff0c;连续不断的推出了多个电竞系列鼠标&…

3. 函数

函数是 JavaScript 编程中最重要的工具之一。用一个值封装一段程序的概念有很多用途。它为我们提供了一种结构化大型程序的方法&#xff0c;可以减少重复&#xff0c;将名称与子程序关联起来&#xff0c;并将这些子程序相互隔离。 函数最明显的应用是定义新的词汇。在散文中创造…

2024 天池云原生编程挑战赛决赛名单出炉,冠军来自中山大学、昆仑数智战队

9 月 20 日&#xff0c;2024 天池云原生编程挑战赛决赛答辩完美落幕&#xff0c;12 支进入决赛的团队用精彩的答辩&#xff0c;为历时 3 个月的大赛画下了圆满的句号。其中&#xff0c;来自中山大学的陈泓仰以及来自昆仑数智的冉旭欣、沈鑫糠、武鹏鹏&#xff0c; 以出色的方案…

Nordic软件二[蓝牙协议栈初始化卡死(时钟源默认外部晶振但是板子是内部RC)问题][BSP代码模块修改管脚和相关机制]

蓝牙协议栈初始化卡死(时钟源默认外部晶振但是板子是内部RC)问题 本文摘录于&#xff1a;https://blog.csdn.net/chengbaojin/article/details/103778150只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 先参考上面的文章做如下修改: …

中国科学院云南天文台博士招生目录

中国科学院云南天文台是专业基础研究与应用研究结合的综合性天文研究机构&#xff08;其前身是1938年中央研究院天文研究所在昆明东郊凤凰山创建的凤凰山天文台&#xff09;&#xff0c;总部在云南省昆明市&#xff0c;设有两个观测站&#xff08;丽江高美古天文观测站和澄江抚…

使用通义灵码,参与开源项目全程纪实

作者&#xff1a;shuipin100-34561 背景 缘起 OceanBase。作为一个充满好奇心的 DBA&#xff0c;一直一来想探寻数据库的内部世界。开源为我们这些好奇的猫打开了一扇新世界的大门。OceanBase 作为分布式关系型数据库的排头兵&#xff0c;自然进入了我的优选名单。起初走进了…

ComfyUI中缺失节点安装一点小小注意事项

加载工作流&#xff0c;遇到了红当当的缺失节点警告窗口&#xff1a; 在ComfyUI-Manager点击安装缺失节点&#xff0c;发现竟然弹出4个&#xff0c;而上面告警窗口中只是缺失3个&#xff0c;究竟是怎么回事呢&#xff0c;刚开始接触ComfyUI时&#xff0c;我也是不管3721&#x…