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

第四阶段-12关于Spring Security框架,RBAC,密码加密原则

关于csmall-passport项目

此项目主要用于实现“管理员”账号的后台管理功能,主要实现:

  • 管理员登录
  • 添加管理员
  • 删除管理员
  • 显示管理员列表
  • 启用 / 禁用管理员

关于RBAC

RBAC:Role-Based Access Control,基于角色的访问控制

在涉及权限管理的应用软件设计中,应该至少需要设计以下3张数据表:

  • 用户表
  • 角色表
  • 权限表

并且,还至少需要2张关联表:

  • 用户与角色的关联表
  • 角色与权限的关联表

关于Spring Security框架

Spring Security主要解决了认证与授权相关的问题。

认证:判断某个账号是否允许访问某个系统,简单来说,就是验证登录

授权:判断是否允许已经通过认证的账号访问某个资源,简单来说,就是判断是否具有权限执行某项操作

添加依赖

在基于Spring Boot的项目中,使用Spring Security需要添加依赖项:

<!-- Spring Boot Security依赖项,用于处理认证与授权相关的问题 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

当在项目中添加以上依赖项后,你的项目会发生以下变化(Spring Boot中的Spring Security的默认行为):

  • 所有的请求都是必须要登录才允许访问的,包括错误的URL

  • 提供了默认的登录页面,当未登录时,会自动重定向到此登录页面

  • 提供了临时的登录账号,用户名是user,密码是启动项目时在控制台中的UUID值(每次重启项目都会不同)

请添加图片描述

  • 当登录成功后,将自动重定向到此前尝试访问的URL,如果此前没有尝试访问某个URL,则重定向到根路径
  • 可以通过 /logout 路径访问到“退出登录”的页面,以实现登出
  • 当登录成功后,POST请求都是不允许的,而GET请求是允许的

关于Spring Security的配置类

在项目的根包下,创建config.SecurityConfiguration类,继承自WebSecurityConfigurerAdapter类,在类上添加@Configuration注解:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
}

然后,在类中重写void configure(HttpSecurity http)方法:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {}}

**注意:**在重写的方法中,不要使用super调用父类的此方法!

由于没有调用父类此方法,再次重启项目后,与此前将有些不同:

  • 所有请求都不再要求登录
  • 登录、登出的URL不可访问

关于登录表单

在Spring Security配置类的configure(HttpSecurity http)方法中,根据是否调用了参数对象的formLogin()方法,决定是否启用登录表单页(/login)和登出页(/logout),例如:

@Override
protected void configure(HttpSecurity http) throws Exception {// 调用formLogin()表示启用登录表单页和登出页,如果未调用此方法,则没有登录表单页和登出页http.formLogin();
}

关于URL的访问控制

在Spring Security配置类的configure(HttpSecurity http)方法中,

// 白名单
// 使用1个星号,表示通配此层级的任意资源,例如:/admin/*,可以匹配 /admin/delete、/admin/add-new
// 但是,不可以匹配多个层级,例如:/admin/*,不可以匹配 /admin/9527/delete
// 使用2个连续的星号,表示通配任何层级的任意资源,例如:/admin/**,可以匹配 /admin/delete、/admin/9527/delete
String[] urls = {"/doc.html","/**/*.js","/**/*.css","/swagger-resources","/v2/api-docs"
};// 配置URL的访问控制
http.authorizeRequests() // 配置URL的访问控制.mvcMatchers(urls) // 匹配某些URL.permitAll() // 直接许可,即:不需要通过认证就可以直接访问.anyRequest() // 任何请求.authenticated(); // 以上配置的请求需要是通过认证的

使用临时的自定义账号实现登录

可以自定义类,实现UserDetailsService接口,并保证此类是组件类,则Spring Security框架会基于此实现类来处理认证。

在项目的根包下创建security.UserDetailsServiceImpl类,实现UserDetailsService接口,并在类上添加@Service注解,重写接口中定义的抽象方法:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return null;}
}

当项目中存在UserDetailsService类型的组件对象时,尝试登录时,Spring Security会自动使用登录表单提交过来的用户名来调用以上loadUserByUsername()方法,并得到UserDetails类型的对象,此对象中应该包含用户的相关信息,例如密码、账号状态等,接下来,Spring Security会自动使用登录表单提交过来的密码与UserDetails中的密码进行对比,且判断账号状态,以决定此账号是否能够通过认证。

所以,重写以上方法:

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {// 假设存在可用的账号信息:用户名(root),密码(123456)if ("root".equals(s)) {UserDetails userDetails = User.builder().username("root").password("123456").disabled(false).accountLocked(false).accountExpired(false).credentialsExpired(false).authorities("暂时给个山寨权限,暂时没有作用,只是避免报错而已").build();return userDetails;}return null;
}

**提示:**当项目中存在UserDetailsService类型的组件对象时,Spring Security框架不再提供临时的账号(用户名为user密码为启动项目时的UUID值的账号)!

**注意:**Spring Security在处理认证时,要求密码必须经过加密码处理,即使你执意不加密,也必须明确的表示出来!

SecurityConfiguration中,通过@Bean方法配置PasswordEncoder,并返回NoOpPasswordEncoder的对象,表示“不对密码进行加密处理”:

@Bean
public PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();
}

完成后,重启项目,通过/login可以测试访问。

使用数据库中的账号数据实现登录

需要实现“根据用户名查询用户的登录信息”,需要执行的SQL语句大致是:

select id, username, password, enable from ams_admin where username=?

在项目的根包下创建pojo.vo.AdminLoginInfoVO类:

@Data
public class AdminLoginInfoVO implements Serializable {private Long id;private String username;private String password;private Integer enable;
}

AdminMapper.java接口中添加抽象方法:

AdminLoginInfoVO getLoginInfoByUsername(String username);

AdminMapper.xml中配置以上抽象方法映射的SQL:

<select ...></select><sql></sql><resultMap></resultMap>

AdminMapperTests中编写并执行测试:

接下来,在UserDetailsServiceImpl中,先自动装配AdminMapper对象,然后,调整loadUserByUsername()方法:

@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {// 使用参数s作为参数,调用AdminMapper对象的getLoginInfoByUsername()方法执行查询// 判断查询结果是否为null// 是:无此用户名对应的账号信息,返回null// 返回UserDetails对象// username:来自查询结果// password:暂时写死为123456,后续再改成来自查询结果// disable:来自查询结果中的enable,判断enable是否为0// accountExpired等:参考此前的Demo,将各值写死
}

完成后,可以使用数据库中的账号测试登录(暂时不方便测试密码)。
tLoginInfoByUsername()方法执行查询
// 判断查询结果是否为null
// 是:无此用户名对应的账号信息,返回null

// 返回UserDetails对象
// username:来自查询结果
// password:暂时写死为123456,后续再改成来自查询结果
// disable:来自查询结果中的enable,判断enable是否为0
// accountExpired等:参考此前的Demo,将各值写死

}


完成后,可以使用数据库中的账号测试登录(暂时不方便测试密码)。#### 密码为什么需要加密如果未加密,将密码的原文(原始密码)直接存入到数据库中,可以被轻松获取账户的关键信息!以目前主流的网络结构和技术,通常,密码加密主要防范的是内部工作人员(能够接触到服务器的人员)!需要注意:即使密码加密了,也要防范相关的内部工作人员,例如程序员!#### 如何对密码进行加密直接使用现有的某种算法,也就是说,不会自行设计某个算法!#### 使用什么算法对密码进行加密一定**不可以**使用**加密算法**!因为所有加密算法都是可以被逆向运算的,也就是说,可以根据加密得到的结果,进行反向运算,还原出原始密码!通常,加密算法仅用于保障数据在传输过程中的安全!在对密码进行加密处理并存入到数据库中时,应该使用**不可逆**的算法!许多**哈希算法**,或基于哈希算法的**消息摘要算法**都是不可逆的!#### 关于消息摘要算法典型的消息摘要算法有:- SHA(Secure Hash Algorithm)家族算法- SHA-1(160位算法)- SHA-256(256位算法)- SHA-384(384位算法)- SHA-512(512位算法)
- MD(Message Digest)系列算法- MD2(128位算法)- MD4(128位算法)- MD5(128位算法)消息摘要算法原本是用于验证接收方所接收的数据与发送方所发出的数据是否一致。消息摘要算法有几个典型特征:- 如果消息相同,则摘要一定相同
- 如果消息不同,则摘要极大概率会不同- 必然存在n个不同的消息,摘要完全相同
- 使用同一种算法时,无论消息长度是多少,摘要的长度是固定的#### 在项目中使用MD5算法在Spring框架中,提供了`DigestUtils`,可以非常便利的使用MD5算法将消息处理为摘要:```java
public class Md5Tests {@Testvoid encode() {String rawPassword = "123456";String encodedPassword = DigestUtils.md5DigestAsHex(rawPassword.getBytes());System.out.println("原文:" + rawPassword);System.out.println("密文:" + encodedPassword);}}

算法位数对安全性的影响

以MD5算法为例,它是128位的算法,即其运算结果是由128个二进制位组成的,所以,其运算结果的排列组件有2的128次方种,这个数字转换成十进制是:340282366920938463463374607431768211456。

理论上,使用MD5算法时,要想找到2个不同的消息运算出相同的摘要,概率应该是340282366920938463463374607431768211456分之1!或者,也可以认为,你至少需要运算340282366920938463463374607431768211456次,才可以找到2个不同的消息运算出相同的摘要。

相比之下,更高位数的算法,理论上,更难找出不同的消息运算出相同的摘要!

一般情况下,由于MD5的安全系数已经较高,所以,不一定需要使用位数更高的算法!

关于消息摘要算法的破解 – 学术

当2个不同的消息,运算出相同的摘要,从学术上,称之为“碰撞”。

理论上,128位的算法,其碰撞概率应该是2的128次方分之1。

关于消息算法的破解,主要是研究其碰撞概率,是否可以使用更少次数的运算实现碰撞!而不是尝试根据摘要进行逆向运算还原出消息!

目前,SHA-1算法已经被视为不安全的算法,它是160位算法,经过研究,只需要经过2的60几次方的运算就可以发生碰撞,即SHA-1的安全系数与60几位的算法几乎相当。

关于消息摘要算法的“破解” – 根据摘要得到消息

网上有许多平台可以做到“根据密文还原出原文”,这些平台都是记录大量的原文与密文的对应关系,当尝试“破解”时,本质上是在做查询操作,大概是:

select 原文 from 数据表 where 密文=?

例如,某平台明确的说明了:

本站针对md5、sha1、sha256等全球通用公开的加密算法进行反向查询,通过穷举字符组合的方式,创建了明文密文对应查询数据库,创建的记录约90万亿条,占用硬盘超过500TB,查询成功率95%以上,很多复杂密文只有本站才可查询。本站专注于各种公开算法,已稳定运行17年。

如果密码可以使用全部的可打印字符,7位长度的密码的排列组合有约70万亿种,8位长度的密码的排列组件在此基础上需要乘以95,则以上平台不可能记录8位长度的所有明文密文的对应关系!也就是说,只要原始密码的长度达到8位,这些平台就可能无法根据密文查询出原文,原始密码的长度越长,或原始密码的强度越高(由多种元素组成,例如大小写字母、数字、标点符号),被这些平台收录的可能性就越低!

如何进一步保障用户的密码安全 – 加盐

盐值的本质就只是一个外部人员很难预测到的字符串,它将作用于处理加密过程中,例如:

// 以下1行定义了盐值
String salt = "fsd4W87i78oiAsUu43IEF";String rawPassword = "123456";
String encodedPassword = DigestUtils.md5DigestAsHex((rawPassword + salt).getBytes());
//       ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 将原始密码和盐值一起被处理System.out.println("原文:" + rawPassword);
System.out.println("密文:" + encodedPassword);

当然,盐值应该如何使用,也没有明确的规定,你可以:

String encodedPassword = DigestUtils.md5DigestAsHex((rawPassword + salt).getBytes());

或者:

String encodedPassword = DigestUtils.md5DigestAsHex((salt + rawPassword).getBytes());

甚至:

String encodedPassword = DigestUtils.md5DigestAsHex((salt + rawPassword + salt + rawPassword + salt + salt).getBytes());

总而言之,使用盐的目的是”使得被MD5运算的原始数据变得更加复杂“。

你甚至可以使用随机的盐值,例如:

String salt = UUID.randomUUID().toString(); // 使用UUID作为盐值
String rawPassword = "123456";
String encodedPassword = DigestUtils.md5DigestAsHex((rawPassword + salt).getBytes());

使用随机盐时必须注意:你需要将随机的盐值保存下来,否则,后续你将无法验证密码!

至于如何保存,方式有许多,例如在数据表中添加新的字段来保存盐值,或者,把盐值直接作为密码的一部分,例如:

String salt = UUID.randomUUID().toString();
String rawPassword = "123456";
String encodedPassword = DigestUtils.md5DigestAsHex((rawPassword + salt).getBytes()) + salt;
System.out.println("盐值:" + salt);
System.out.println("原文:" + rawPassword);
System.out.println("密文:" + encodedPassword);

密码加密原则 – 小结

关于密码加密处理:

  • 不可以使用加密算法,只能使用消息摘要算法或其它哈希算法
    • 不建议使用SHA-1
  • 应该要求用户使用更长的、强度更高的密码,避免容易被反查(根据密文查询得到原文)
  • 应该进行加盐处理
  • 你还可以使用多重加密(使用同一个算法,或不同算法,对数据进行反复运算)
  • 可以考虑使用位数更长的算法(在MD5的基础上,改为使用SHA-256 / SHA-384 / SHA-512)

**注意:**无论你综合使用以上哪些做法,最终,可能都无法避免内部人员泄密(算法、加密参数、加密过程、密文都是破解时的已知条件)导致的穷举式的暴力破解,而BCrypt算法是被设计得运算效率极低的算法,可以非常有效的避免被暴力破解。

相关文章:

第四阶段-12关于Spring Security框架,RBAC,密码加密原则

关于csmall-passport项目 此项目主要用于实现“管理员”账号的后台管理功能&#xff0c;主要实现&#xff1a; 管理员登录添加管理员删除管理员显示管理员列表启用 / 禁用管理员 关于RBAC RBAC&#xff1a;Role-Based Access Control&#xff0c;基于角色的访问控制 在涉及…...

JPA——Date拓展之Calendar

Java Calendar 是时间操作类,Calendar 抽象类定义了足够的方法&#xff0c;在某一特定的瞬间或日历上&#xff0c;提供年、月、日、小时之间的转换提供方法 一、获取具体时间信息 1. 当前时间 获取此刻时间的年月日时分秒 Calendar calendar Calendar.getInstance(); int …...

一文吃透 Spring 中的 AOP 编程

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

Apple主推的智能家居是什么、怎么用?一篇文章带你从零完全入门 HomeKit

如果你对智能家居有所了解&#xff0c;那应该或多或少听人聊起过 HomeKit。由 Apple 开发并主推的的 HomeKit 既因为产品选择少、价格高而难以成为主流&#xff0c;又因其独特的优秀体验和「出身名门」而成为智能家居领域的焦点。HomeKit 究竟是什么&#xff1f;能做什么&#…...

SpringCloud系列知识快速复习 -- part 1(SpringCloud基础知识,Docker,RabbitMQ)

SpringCloud知识快速复习SpringCloud基础知识微服务特点SpringCloud常用组件服务拆分和提供者与消费者概念Eureka注册中心原理Ribbon负载均衡原理负载均衡策略饥饿加载Nacos注册中心服务分级存储模型权重配置环境隔离Nacos与Eureka的区别Nacos配置管理拉取配置流程配置热更新配…...

2023上半年北京/上海/广州/深圳NPDP产品经理认证报名

产品经理国际资格认证NPDP是国际公认的唯一的新产品开发专业认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会&#xff08;PDMA&#xff09;成立于1979年…...

面试半年,总结了1000道2023年Java架构师岗面试题

半年前还在迷茫该学什么&#xff0c;怎样才能走出现在的困境&#xff0c;半年后已经成功上岸阿里&#xff0c;感谢在这期间帮助我的每一个人。 面试中总结了1000道经典的Java面试题&#xff0c;里面包含面试要回答的知识重点&#xff0c;并且我根据知识类型进行了分类&#xf…...

通过MySQL驱动拦截器实现执行sql耗时计算

文章目录背景具体实现MySQL5MySQL6MySQL8使用方法测试结果背景 公司的一个需求&#xff0c;公司既有的链路追踪日志组件要支持MySQL的sql执行时间打印&#xff0c;要实现链路追踪常用的手段就是实现第三方框架或工具提供的拦截器接口或者是过滤器接口&#xff0c;对于MySQL也不…...

易基因|独家分享:高通量测序后的下游实验验证方法——DNA甲基化篇

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。此前&#xff0c;我们分享了DNA甲基化研究的测序数据挖掘思路&#xff08;点击查看详情&#xff09;&#xff0c;进而鉴定出研究的目的基因或目标区域的DNA甲基化。做完测序后&#xff0c;…...

java基础系列(七) 同步和异步理解

一. 问题描述 同步传输和异步传输是web和数据库的重要知识点&#xff0c;会被很多老师强调。那么&#xff0c;它们有什么相同点和不同点&#xff1f;它们对于我们学习编程的意义在哪里&#xff1f; 二. 概念 首先什么是同步和异步&#xff1f; 这里的同步是指&…...

吉林大学 程序设计基础 2022级 OJ期末考试 2.23

本人能力有限&#xff0c;发出只为帮助有需要的人。 以下为实验课的复盘&#xff0c;内容会有大量失真&#xff0c;请多多包涵。 1.双手剑士的最优搭配 每把剑有攻击力和防御力两个属性。双手剑士可以同时拿两把剑&#xff0c;其得到攻击力为两把剑中的攻击力的最大值&#…...

【项目实战】SpringMVC拦截器实战 - 自定义拦截器防止重复提交

一、背景说明 如何能够实现防止重复提交呢?以下是一种可选的方式。 二、代码实战 2.1 注册重复提交拦截器到SpringMVC中 @Configuration @AllArgsConstructor public class ResourcesConfig implements WebMvcConfigurer {private final RepeatSubmitInterceptor repeatSu…...

C++ STL:容器 Container

文章目录1、序列容器1.1、容器共性1.2、vectorvector 结构* vector 扩容原理* vector 迭代器失效1.3、dequedeque 结构deque 迭代器deque 模拟连续空间1.4、listlist 特殊操作list 结构list 迭代器2、关联式容器2.1、容器共性2.2、容器特性3、无序关联式容器3.1、容器共性3.2、…...

urllib之urlopen和urlretrieve的headers传入以及parse、urlparse、urlsplit的使用

urllib库是什么?urllib库python的一个最基本的网络请求库&#xff0c;不需要安装任何依赖库就可以导入使用。它可以模拟浏览器想目标服务器发起请求&#xff0c;并可以保存服务器返回的数据。urllib库的使用&#xff1a;1、request.urlopen(1)只能传入url的方式from http.clie…...

【C++】二叉搜索树的模拟实现

一、概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左右子树也分别…...

HNU工训中心:元器件及测量基础实验报告

工训中心的牛马实验 1.实验目的 1.熟悉测量验证常用元器件参数、 并采用替代法(测量回路电流)测量其伏安特性的方法。 2.熟悉测量误差及减小测量误差注意事项 2.实验仪器和器材 1.实验仪器. 直流稳压电源型号:IT6302 台式多用表型号:UT805A 2.实验( 箱)器材 电路实验箱…...

博客系统--自动化测试

项目体验地址&#xff08;账号&#xff1a;123&#xff0c;密码&#xff1a;123&#xff09;http://120.53.20.213:8080/blog_system/login.html项目后端说明&#xff1a;http://t.csdn.cn/32Nnv项目码云Gitee地址&#xff1a;https://gitee.com/GoodManSS/project/tree/master…...

Day903.自增主键不能保证连续递增 -MySQL实战

自增主键不能保证连续递增 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于自增主键不能保证连续递增的内容。 MySql保证了主键是自增&#xff0c;但不相对连续&#xff1b;帮助开发人员快速识别每个行的唯一性&#xff0c;并提高查询效率。 自增主键可以让主键索引…...

02-MyBatis查询-

文章目录Mybatis CRUD练习1&#xff0c;配置文件实现CRUD1.1 环境准备Debug01: 别名mybatisx报错1.2 查询所有数据1.2.1 编写接口方法1.2.2 编写SQL语句1.2.3 编写测试方法1.2.4 起别名解决上述问题1.2.5 使用resultMap解决上述问题1.2.6 小结1.3 查询详情1.3.1 编写接口方法1.…...

外盘国际期货招商:2023年3月关注日历,把握重要投资机会

2023年3月大事件日历 关注大事日历&#xff0c;把握重要投资机会 3月1日&#xff1a;马斯克推出特斯拉宏图第三篇章 3月1-2日&#xff1a;G20外长会议 3月4-5日&#xff1a;全国两会召开 3月9日&#xff1a;中国2月CPI、PPI数据 待定&#xff08;前次进行日期&#xff1a…...

Linux学习(9.1)文件系统的简单操作

以下内容转载自鸟哥的Linux私房菜 原文&#xff1a;鸟哥的 Linux 私房菜 -- Linux 磁盘与文件系统管理 (vbird.org) 磁盘与目录的容量 df&#xff1a;列出文件系统的整体磁盘使用量&#xff1b;du&#xff1a;评估文件系统的磁盘使用量(常用在推估目录所占容量) df du 实体…...

Hadoop综合案例 - 聊天软件数据

目录1、聊天软件数据分析案例需求2、基于Hive数仓实现需求开发2.1 建库2.2 建表2.3 加载数据2.4 ETL数据清洗2.5 需求指标统计---都很简单3、FineBI实现可视化报表3.1 FineBI介绍3.2 FineBI配置数据3.3 构建可视化报表1、聊天软件数据分析案例需求 MR速度慢—引入hive 背景&a…...

Python进阶-----面向对象1.0(对象和类的介绍、定义)

目录 前言&#xff1a; 面向过程和面向对象 类和对象 Python中类的定义 &#xff08;1&#xff09;类的定义形式 &#xff08;2&#xff09;深层剖析类对象 前言&#xff1a; 感谢各位的一路陪伴&#xff0c;我学习Python也有一个月了&#xff0c;在这一个月里我收获满满…...

天猫淘宝企业服务为中小微企业打造供应链智能协同网络,让采购不再将就!丨爱分析报告

编者按&#xff1a;近日天猫淘宝企业服务&爱分析联合发布《2023中小微企业电商采购白皮书》&#xff0c;为中小微企业采购数字化带来红利。 某水泵企业&#xff1a;线上客户主要是中小微企业&#xff0c;线上业绩遇到瓶颈&#xff0c;如何突破呢&#xff1f;某焊割设备企业…...

基于四信网络摄像机的工业自动化应用

方案背景 随着数控机床被广泛的应用在工业生产中&#xff0c;数控技术发展成为制造业的核心。 鉴于数控机床的复杂性&#xff0c;以及企业人力储备有限&#xff0c;设备的监控和维护必须借助外部力量&#xff0c;而如何实现车间实时监测成了目前迫切解决的问题。 方案需求 ①兼…...

软件测试2

一 web掐断三大核心技术 HTML&#xff1a;负责网页的结构 CSS&#xff1a;负责网页的美化 JS&#xff1a;负责网页的行为 二 工具的使用 改变HBuilder文字的大小&#xff1a; 工具-视觉主题设置-大小22-确定 三 html简介 中文定义&#xff1a;超文本标记语言 新建一个html…...

(二分查找)leetcode162. 寻找峰值

文章目录一、题目1、题目描述2、基础框架3、原题链接二、解题报告1、思路分析2、时间复杂度3、代码详解三、本题小知识一、题目 1、题目描述 峰值元素是指其值严格大于左右相邻值的元素。 给你一个整数数组 nums&#xff0c;找到峰值元素并返回其索引。数组可能包含多个峰值…...

spring boot 配合element ui vue实现表格的批量删除(前后端详细教学,简单易懂,有手就行)

目录 一.前言&#xff1a; 二. 前端代码&#xff1a; 2.1.element ui组件代码 2.2删除按钮 2.3.data 2.4.methods 三.后端代码&#xff1a; 一.前言&#xff1a; 研究了其他人的博客&#xff0c;找到了一篇有含金量的&#xff0c;进行了部分改写实现前后端分离&#xff0…...

hiveSQL开窗函数详解

hive开窗函数 文章目录hive开窗函数1. 开窗函数概述1.1 窗口函数分类1.2 窗口函数和普通聚合函数的区别2. 窗口函数的基本用法2.1 基本用法2.2 设置窗口的方法2.2.1 window_name2.2.2 partition by2.2.3 order by 子句2.2.4 rows指定窗口大小窗口框架2.3 开窗函数中加 order by…...

深度学习基础实例与总结

一、神经网络 1 深度学习 1 什么是深度学习&#xff1f; 简单来说&#xff0c;深度学习就是一种包括多个隐含层 (越多即为越深)的多层感知机。它通过组合低层特征&#xff0c;形成更为抽象的高层表示&#xff0c;用以描述被识别对象的高级属性类别或特征。 能自生成数据的中…...

在 WIndows 下安装 Apache Tinkerpop (Gremlin)

一、安装 JDK 首先安装 Java JDK&#xff0c;这个去官网下载即可&#xff0c;我下载安装的 JDK19&#xff08;jdk-19_windows-x64_bin.msi&#xff09;&#xff0c;细节不赘述。 二、去 Tinkerpop 网站下载 Gremlin 网址&#xff1a;https://tinkerpop.apache.org/ 点击下面…...

从软件的角度看待PCI和PCIE(一)

1.最容易访问的设备是什么&#xff1f; 是内存&#xff01; 要读写内存&#xff0c;知道它的地址就可以了&#xff0c;不需要什么驱动程序&#xff1b; volatile unsigned int *p 0xffff8811; unsigned int val; *p val; val *p;只有内存能这样简单、方便的使用吗&#xf…...

DSP_TMS320F28377D_ADC学习笔记

前言 DSP各种模块的使用&#xff0c;基本上就是 GPIO复用配置、相关控制寄存器的配置、中断的配置。本文主要记录本人对ADC模块的学习笔记。TMS320F28377D上面有24路ADC专用IO&#xff0c;这意味着不需要进行GPIO复用配置。 只需要考虑相关控制寄存器和中断的配置。看代码请直…...

springcloud3 Nacos中namespace和group,dataId的联系

一 Namespance和group和dataId的联系 1.1 3者之间的联系 话不多说&#xff0c;上答案&#xff0c;如下图&#xff1a; namespance用于区分部署环境&#xff0c;group和dataId用于逻辑上区分两个目标对象。 二 案例&#xff1a;实现读取注册中心的不同环境下的配置文件 …...

[YOLO] yolo理解博客笔记

YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的过程详细解读 YOLO v2和V3 关于设置生成anchorbox&#xff0c;Boundingbox边框回归的个人理解https://blog.csdn.net/shenkunchang1877/article/details/105648111YOLO v1网络结构计算 Yolov1-pytorch版 …...

清华源pip安装Python第三方包

一、更换PIP源PIP源在国外&#xff0c;速度慢&#xff0c;可以更换为国内源&#xff0c;以下是国内一些常用的PIP源。豆瓣(douban) http://pypi.douban.com/simple/ (推荐)清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/阿里云 http://mirrors.aliyun.com/pypi/simple/中…...

python线程池【ThreadPoolExecutor()】批量获取博客园标题数据

转载&#xff1a;蚂蚁学python 网址&#xff1a;【【2021最新版】Python 并发编程实战&#xff0c;用多线程、多进程、多协程加速程序运行】 https://www.bilibili.com/video/BV1bK411A7tV/?p8&share_sourcecopy_web&vd_sourced0ef3d08fdeef1740bab49cdb3e96467实战案…...

LearnOpenGL-入门-8.坐标系统

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject LearnOpenGL中文官网&#xff1a;https://learnopengl-cn.github.io/ 文章目录坐标系统概述局部空间世界空…...

windows10使用wsl2安装docker

配环境很麻烦&#xff0c;想利用docker的镜像环境跑一下代码整个安装过程的原理是&#xff1a;windows使用docker&#xff0c;必须先安装一个linux虚拟机&#xff0c;才可运行docker&#xff0c;而采用wsl2安装虚拟机是目前最好的方法第一步 windows安装wsl2控制面板->程序-…...

Javascript的API基本内容(六)

一、正则表达式 1.定义规则 const reg /表达式/ 其中/ /是正则表达式字面量正则表达式也是对象 2.使用正则 test()方法 用来查看正则表达式与指定的字符串是否匹配如果正则表达式与指定的字符串匹配 &#xff0c;返回true&#xff0c;否则false 3.元字符 比如&#xff0…...

电压放大器和电流放大器的区别是什么意思

在日常电子实验测试中&#xff0c;很多电子工程师都会使用到电压放大器和电流放大器&#xff0c;但是很多新手工程师却无法区分两者的区别&#xff0c;下面就让安泰电子来为我们讲解电压放大器和电流放大器的区别是什么意思。 一、电压放大器介绍&#xff1a; 电压放大器是一种…...

cast提前!最简单有效的神经网络优化方法,没有之一!

做优化有时候真的很头疼&#xff0c;绞尽脑汁的想怎么做算法等价&#xff0c;怎么把神经网络各层指令流水起来&#xff0c;在确保整网精度的同时&#xff0c;又有高性能。 但有时做了半天&#xff0c;却发现流水根本就流不起来&#xff0c;总是莫名其妙地被卡住。 真的是一顿…...

LeetCode刷题——动态规划(C/C++)

文章目录[简单]买股票的最佳时机[简单]爬楼梯[中等]最长递增子序列[中等]最大连续子数组和[简单]买股票的最佳时机 原题链接 题解 min&#xff1a;今天之前买股的最低价 res&#xff1a;最大利润 每一天比较今天和往前的最低价差值能否比最大利润还大 class Solution { publ…...

车载智能终端TBOX

YD886 终端设备是基于GSM/WCDMA全网通讯方式的GPS定位移动终端,车载设备具有强大的车辆监控管理、CAN总线数据采集等功能&#xff0c;可以满足不同用户的需求&#xff0c;同时具备汽车行驶记录功能扩展应用。具体功能请以终端实际情况为准&#xff01; 一、移动管家 车载智能终…...

技术分担产品之忧(上):挑选有业务专家潜力的人

你好&#xff0c;我是王植萌&#xff0c;去哪儿网的高级技术总监、TC主席。从2014年起&#xff0c;担任一个部门的技术负责人&#xff0c;有8年技术总监经验、5年TC主席的经验。这节课我会从去哪儿网产研融合的经验出发&#xff0c;和你聊一聊怎么让技术分担产品之忧。 技术分…...

UVa 12569 Planning mobile robot on Tree (EASY Version) 树上机器人规划(简单版) BFS 二进制

题目链接&#xff1a;Planning mobile robot on Tree (EASY Version) 题目描述&#xff1a; 给定一棵树&#xff0c;树上有一个位置存在一个机器人&#xff0c;其他mmm个位置存在石头&#xff0c;保证初始状态一个结点最多一个物体&#xff08;一个石头或者一个机器人或者为空…...

intel的集成显卡(intel(r) uhd graphics) 配置stable diffusion

由于很多商务本没有独立显卡&#xff0c;只有Intel的集成显卡&#xff0c;在配置安装stable diffusion 时候需要特殊对待&#xff0c;参考不少帖子&#xff0c;各取部分现稍加整合。整体思路分两个部分&#xff1a;第一步是先配置环境&#xff0c;主要是安装Anaconda Pytorch&…...

【数据库的基础知识(2)】

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…...

Docker部署实战

文章目录Docker部署应用准备制作容器镜像启动容器上传镜像docker exec数据卷&#xff08;Volume&#xff09;声明原理实践Docker部署 应用准备 这一次&#xff0c;我们来用 Docker 部署一个用 Python 编写的 Web 应用。这个应用的代码部分&#xff08;app.py&#xff09;非常…...

RestTemplate 相关使用

RestTemplate介绍简单接口调用&#xff08;getForObject&#xff09;添加 Header 和 Cookie&#xff08;exchange&#xff09;介绍 在项目中&#xff0c;当我们需要远程调用一个 HTTP 接口时&#xff0c;我们经常会用到 RestTemplate 这个类。这个类是 Spring 框架提供的一个工…...