Spring Secuirty 密码加密认证讲解

2023-05-16

目录

一、密码加密介绍

1.1 常见加密的策略

1.Hash 算法

2.单向自适应函数

二、Security加密结构 

2.1 PasswordEncoder

2.2 密码认证流程 

2.3 DeletaingPasswordEncoder 

      1.为什么默认一个代理类不是具体的呢?

     2. DeletaingPasswordEncoder 的装配原理

 3.如何自定义PasswordEncoder 

2.3 密码升级

        1.原理

2.升级流程

3.自定义密码升级


一、密码加密介绍

2011 年12⽉21 ⽇,有⼈在⽹络上公开了⼀个包含600万个 CSDN ⽤户资料

的数据库,数据全部为明⽂储存,包含⽤户名、密码以及注册邮箱。事件

发⽣后 CSDN 在微博、官⽅⽹站等渠道发出了声明,解释说此数据库系

2009 年备份所⽤,因不明原因泄漏,已经向警⽅报案,后⼜在官⽹发出了公开道歉信。在接下来的⼗多天⾥,⾦⼭、⽹易、 京东、当当、新浪等多家公司被卷⼊到这次事件中。整个事件中最触⽬惊 ⼼的莫过于 CSDN 把⽤户密码明⽂存储,由于很多⽤户是多个⽹站共⽤⼀ 个密码,因此⼀个⽹站密码泄漏就会造成很⼤的安全隐患。由于有了这么

多前⻋之鉴,我们现在做系统时,密码都要加密处理。

在前⾯的案例中,凡是涉及密码的地⽅,我们都采⽤明⽂存储,在实际项⽬中这肯定是不可取的,因为这会带来极⾼的安全⻛险。在企业级应⽤ 中,密码不仅需要加密,还需要加 盐 ,最⼤程度地保证密码安全。

加盐的作用就是为了防止数据库被攻破后看到数据库的加密的密码,但是黑客可以用过常用的一些加密算法进行破解此时这个盐的作用的就出现了,而这个盐有是一个随机生成的字符串,这个盐值是需要进行保存的,在进行显示的时候。而盐值有的保存用户表,这种方式也是可用行的,但是在计算的需要将盐进行散列或者前后进行分散多次加盐以保证密码的安全性,也有的将盐存放到redis里和数据库是分开的。

1.1 常见加密的策略

1.Hash 算法

最早我们使用类似 SHA-256 、SHA-512 、MD5 等这样的单向 Hash 算法。用户注册成功后,保存在数据库中不再是用户的明文密码,而是经过 SHA-256 加密计算的一个字符串,当用户进行登录时,用户输入的明文密码用 SHA-256 进行密码,加密成功之后,再和存储在数据库中的密码进行比对,进而确定用户登录信息是否有效。如果系统遭到攻击,最多也只是存储在数据库中密文被泄露。

这样就绝对安全了吗?由于彩虹表这种攻击方式的存在以及随着计算机硬件的发展,每秒执行数十亿次 HASH 计算已经变得轻轻松松,这意味着即便给密码加密加盐也不再安全。

参考: 彩虹表彩虹表彩虹表

2.单向自适应函数

单向自适应函数这种方式加密是可逆的,但是相同的密码无法得到同一个结果。每次加密都是生成新的结果。比较的时候,会把加密的结果解析成明文比较。验证口令的系统总是可以获取口令的明文的

在 Spring Security 中,我们现在是用一种自适应单向函数 (Adaptive One-way Functions) 来处理密码问题,这种自适应单向函数在密码匹配时,会有意占用大量系统资源 (例如 CPU、内存等),这样可以增加恶意用户攻击系统的难度。在 Spring Security 中,开发者可以通过 bcrypt、PBKDF2、sCrypt 以及 argon2 来体验这种自适应单向函数加密。由于自适应单向函数有意占用大量系统资源,因此每个登录认证请求都会大大降低应用程序的性能,但是 Spring Security 不会采取任何措施来提高密码验证速度,因为它正是通过这种方式来增强系统的安全性。

  • BCryptPasswordEncoder

        BCryptPasswordEncoder 使⽤ bcrypt 算法对密码进⾏加密,为了提⾼密码的安全性,bcrypt算法故意降低运⾏速度,以增强密码破解的难度。同时 BCryptP asswordEncoder “为⾃⼰带盐”开发者不需要额外维护⼀个“盐” 字段,使⽤ BCryptPasswordEncoder 加密后的字符串就已经“带盐”了,即使相同的明⽂每次⽣成的加密字符串都不相同。

  • Argon2PasswordEncoder

Argon2PasswordEncoder 使⽤ Argon2 算法对密码进⾏加密,Argon2 曾在 Password Hashing Competition 竞赛中获胜。为了解决在定制硬件上密码容易被破解的问题 Argon2也是故意降低运算速度,同时需要⼤量内存,以确保系统的安全性。

  • Pbkdf2PasswordEncoder

Pbkdf2PasswordEncoder 使⽤ PBKDF2 算法对密码进⾏加密,和前⾯⼏种类似,PBKDF2 算法也是⼀种故意降低运算速度的算法,当需要 FIPS (Federal Information Processing Standard,美国联邦信息处理标准)认证时, PBKDF2 算法是⼀个很好的选择。

  • SCryptPasswordEncoder

SCryptPasswordEncoder 使⽤scrypt 算法对密码进⾏加密,和前⾯的⼏种类似,serypt 也是⼀种故意降低运算速度的算法,⽽且需要⼤量内存。

所有的算法都是通过增加执行时间来进行安全的功能

二、Security加密结构 

2.1 PasswordEncoder

public interface PasswordEncoder {
	String encode(CharSequence rawPassword);
	boolean matches(CharSequence rawPassword, String encodedPassword);
	default boolean upgradeEncoding(String encodedPassword) 
    {
		return false; } 
	
}
  • encode 用来进行明文加密的
  • matches 用来比较密码的方法 (明文密码和数据库密码进行比对的)
  • upgradeEncoding 用来给密码进行升级的方法 

     SpringSecurity 就是通过这个接口进行完成密码的加密和认证的 。这个父接口,它有这众多子类,可以通过他的子类来定义不同的密码加密策略。

        

db0adb3c0fd0eb4d68c0c47bf8f2d5ca.png

2.2 密码认证流程 

        一下是默认的SpringSecurity 的认证流程,没有进行配置改动。

       1.首先会走到UserNamePasswordAuthenticationFilter (默认表单认证)在attemptAuthentication 里会调用 AuthenticationManager 的authenticate 方法进行认证。

 2.进入到AuthenticationManger的认证方法 

3.遍历所有 AuthenticationProvider 判断那个支持

 4.最终默认都不支持会调用parent 进行处理 ,这里为什么会parent 不展开说了。

 5.调用 AbstractUserDetailsAuthenticationProvider 的认证方法

6.执行  retrieveUser 查询用户是否存在

 7.调用 DaoAuthenticationProvider 的 retrieveUser 的查询方法 

 8.调用密码的认证

9.调用  DaoAuthenticationProvider 的 additionalAuthenticationChecks 密码认证方法

10.调用 DelegatingPasswordEncoder 的  matches 的认证方法

11.最后进行指定的PasswordEncoder 的方法验证

以上是密码认证的流程,和源码。

         通过对认证流程源码的分析得知,实际密码比较是由PasswordEncoder完成的,因此只需要使用PasswordEncoder 不同的实现就可以实现不同方式加密

        其实为什么默认是DeletatingPasswordEncoder 不是具体的呢?

2.3 DeletaingPasswordEncoder 

      1.为什么默认一个代理类不是具体的呢?

        

    passwordEncorder 在SpringSecurity 默认实现并不是使用具体的某个实现类而是DelegatingPasswordEnocoder ,它是一个代理类,它并不是具体的实现,它是通过这个类将传来的id(也就是{noop})去拿到一种具体的实现,这样的好处是向上兼容 也能向下兼容,不管使用那种加密方式可以处理

spring Security 把所有的加密方式放到一个map中根据id去比较找对应的加密类,根据{}里的值去比较。

不固定数据的密码的加密就可以在数据存储时携带{noop}类型的数据就可以了,他会被Delegating进行选择处理

默认使用DelegatingPasswordEnocoder 进行密码加密处理,比较灵活只要给定指定的前缀就可以处理,还可以固定死,就直接替换掉 DelegatingPasswordEnocoder 为指定的加密方式类就可以了

  • 兼容性:使用 DelegatingPasswordEncoder 可以帮助需要使用旧密码加密方式的系统顺利迁移到 Spring Security 中, 它允许在同一个系统中同时存储不同的密码加密方案。
  • 便捷性:密码存储的最佳方案不可能一直不变,如果使用 DelegatingPasswordEncoder作为默认的密码加密方案,当需要修改加密方案时,只需要修改很小一部分代码就可以实现。

     2. DeletaingPasswordEncoder 的装配原理

        它是通过 PasswordEncoderFactories 创建出来的 。那么PasswordEncoderFactories 是个什么呢?

        他里面的map保存这所有的加密方式 key 就是 id ,取出的时候是 {noop} 格式的 

public class PasswordEncoderFactories {

	/**
	 * Creates a {@link DelegatingPasswordEncoder} with default mappings. Additional
	 * mappings may be added and the encoding will be updated to conform with best
	 * practices. However, due to the nature of {@link DelegatingPasswordEncoder} the
	 * updates should not impact users. The mappings current are:
	 *
	 * <ul>
	 * <li>bcrypt - {@link BCryptPasswordEncoder} (Also used for encoding)</li>
	 * <li>ldap - {@link org.springframework.security.crypto.password.LdapShaPasswordEncoder}</li>
	 * <li>MD4 - {@link org.springframework.security.crypto.password.Md4PasswordEncoder}</li>
	 * <li>MD5 - {@code new MessageDigestPasswordEncoder("MD5")}</li>
	 * <li>noop - {@link org.springframework.security.crypto.password.NoOpPasswordEncoder}</li>
	 * <li>pbkdf2 - {@link Pbkdf2PasswordEncoder}</li>
	 * <li>scrypt - {@link SCryptPasswordEncoder}</li>
	 * <li>SHA-1 - {@code new MessageDigestPasswordEncoder("SHA-1")}</li>
	 * <li>SHA-256 - {@code new MessageDigestPasswordEncoder("SHA-256")}</li>
	 * <li>sha256 - {@link org.springframework.security.crypto.password.StandardPasswordEncoder}</li>
	 * <li>argon2 - {@link Argon2PasswordEncoder}</li>
	 * </ul>
	 *
	 * @return the {@link PasswordEncoder} to use
	 */
	@SuppressWarnings("deprecation")
	public static PasswordEncoder createDelegatingPasswordEncoder() {
		String encodingId = "bcrypt";
		Map<String, PasswordEncoder> encoders = new HashMap<>();
		encoders.put(encodingId, new BCryptPasswordEncoder());
		encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
		encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
		encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
		encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
		encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
		encoders.put("scrypt", new SCryptPasswordEncoder());
		encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
		encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
		encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
		encoders.put("argon2", new Argon2PasswordEncoder());

		return new DelegatingPasswordEncoder(encodingId, encoders);
	}

	private PasswordEncoderFactories() {}
}

        DeletaingPasswordEncoder 是通过 WebSecurityConfigurerAdapter 里进行自动装配的,

        首先先回去容器里拿,没有就会创建

        创建完成后会将各个UserDetailsService的主要父类的 PasswordEncoder赋值。


  


        这是从容器去找是否有 ,如果容器没有就会通过工厂类进行创建。  

        PasswordEncoderFactories.createDelegatingPasswordEncoder();

    

 3.如何自定义PasswordEncoder 

        通过源码分析得知如果在⼯⼚中指定了PasswordEncoder,就会使⽤指 PasswordEncoder,否则就会使⽤默认DelegatingPasswordEncoder。

        通过以上源码得出,如果想使用指定的PasswordEncoder 直接在容器中创建一个Bean 即可。

    /**
     * 设置指定密码类
     */
    @Bean
    public PasswordEncoder passwordEncoder (){
        return new BCryptPasswordEncoder();
    }

        总结 :如果使用默认的密码加密方式 就需要使用 在数据库的密码 前 {id} 方式来指定加密方式,如果是指定了PasswordEncoder 则不需要

  • 1.默认方式的 DeletatingPasswordEncoder :{noop}123
  • 2.指定加密方式 :$2a$10$RqdGd8FSj9/VrmVi1Me2xOHKkXdgKk9gh6R2LYOdpgFUZIrxflu2C

2.3 密码升级

        1.原理

        

        推荐使⽤DelegatingPasswordEncoder 的另外⼀个好处就是⾃动进⾏密码加密⽅案的升级,这个功能在整合⼀些⽼的系统时⾮常有⽤。

        密码升级推荐使用DelegatingPasswordEncoder 是因为,密码升级会根据DeletatingPasswordEncoder 的默认的 PasswordEncoder 进行升级 随着版本的升级,他默认的PasswordEncoder 也会升级,所以不需要改动源码,如果使用是指定的PasswordEncoder 密码升级的话只会升级成当前PasswordEcoder 要想修改的话则需要修改代码来修改PasswordEncoder 。

        要想更新密码的加密策略就需要在认证成功之后

        密码自动升级是基于ProviderManager 的 authenticate 的AbstractUserDetailsAuthenticationProvider 的 authenticate 的 这个认证方法里调用了子类 AbstractUserDetailsAuthenticationProvider 的 additionalAuthenticationChecks 密码的认证 ,认证完成之后最后调用DaoAuthenticationProvider 的 createSuccessAuthentication 的 在进行判断是否需要进行密码升级,如果需要则完成升级。

层级调用关系

  • AuthenticationProvider 默认的实现类是
    • AbstractUserDetailsAuthenticationProvider 的实现类
      • DaoAuthenticationProvider

            通过对认证流程源码的分析得知,实际密码比较是由PasswordEncoder完成的,因此只需要使用PasswordEncoder 不同的实现就可以实现不同方式加密

#  Spring Security 默认的密码升级流程 

1. 用户输入的账号密码认证成功之后进行  
2. 在ProviderManager 的实现类中的认证方法中最后调用 createSuccessAuthentication 创建认证用户结果的时候进行密码的升级 
3. 默认是基于内存升级 默认基于内存的话,回去先判断它是否是当前DelegatingPasswordEncoder的加密方式的,如果不是则会基于内存去修改。

从以上源码得知 要进行密码升级 当前用户信息是已经完成认证通过的,需要根据用户名称去修改密码就可以了。


# 自定义密码升级步骤
- 1.创建基于数据库的 UserDetatilsService 和 UserDetailsPasswordService 的实现类 (可以合并为一个)
- 2.替换成新建UserDetailsService。
- 3.实现updatePassword 方法,在里面根据用户名修改密码就可以了 

2.升级流程

1.认证完成之后会调用这个方法进行检测是否需要升级代码和封装用户token

2.判断是否需要升级,如果需要则进行密码升级

3.是否升级的判断,首先会先拿着当前的密码去选择出加密方式,在进行判断是否和当前最新的密码方式是否不相同。 

 4.如果返回值为true则进行密码加密的修改

        1.获取当前密码

        2.用当前最新的加密方式进行加密处理

        3.调用 userDetailsPasswordService.  updatePassword 更新密码。

        4.最终返回更新后的用户信息。

以上就是密码自动升级的流程,核心就是通过UserDetailsPasswordService 去更新,所以如果需要自定义的话,那么就去实现UserDetailsPassword就可以了。

3.自定义密码升级

  步骤:

        1.创建UserDetailsPasswordService 的自定义实现 

        2.将默认的UserDetailsPasswordService替换

代码:

public interface MyUserDetailsPasswordService extends UserDetailsPasswordService , UserDetailsService {
    /**
     * 查询用户及其用户角色信息
     */
    @Override
    UserDetails loadUserByUsername(String userName);

    /**
     * 更新密码
     */
    @Override
    UserDetails updatePassword(UserDetails user, String newPassword);

}
/* 
* @Description TODO  更新用户密码和查询用户信息
 */
@Service
public class UserDetailsPasswordService implements MyUserDetailsPasswordService {

    @Autowired
    private UserDAO userDAO ;
    /**
     *  更新用户密码
     * @param user 要更新的用户信息
     * @param newPassword 当前系统加密方式最新的加密后的密码
     * @return 更新密码后的用户信息
     */
    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        if (user!=null){
            int result = userDAO.updatePassword(user.getUsername(), newPassword);
            if (result==1){
                MyUserDetails  myUserDetails = new MyUserDetails();
                BeanUtils.copyProperties(user,myUserDetails);
                myUserDetails.setPassword(newPassword);
                return myUserDetails ;
            }
        }
        return user;
    }

    /**
     * 查询用户信息
     * @param username 用户名称
     * @return 结果
     * @throws UsernameNotFoundException
     */
    @Override
    public MyUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userDAO.loadUserByUsername(username);
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!--指定约束文件-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper 是当前文件的根标签 , 必须的。namespace :叫做命名空间,唯一值。要求你使用dao接口的全限定名称。-->
<mapper namespace="com.bjpowernode.dao.UserDAO">

    <resultMap id="UserTDO" type="com.bjpowernode.entity.MyUserDetails">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="enabled" column="enabled"/>
        <result property="accountNonExpired" column="accountNonExpired"/>
        <result property="accountNonLocked" column="accountNonLocked"/>
        <result property="credentialsNonExpired" column="credentialsNonExpired"/>

        <collection property="roles" javaType="java.util.List" ofType="com.bjpowernode.entity.Role">
            <result property="id" column="roleId"/>
            <result property="name" column="name"/>
            <result property="nameZh" column="name_zh"/>
        </collection>
    </resultMap>
    <!--密码更新-->
    <update id="updatePassword">
        update user set password = #{newPassword} where username = #{username}
    </update>

    <!--根据用户查询-->
    <select id="loadUserByUsername" resultType="com.bjpowernode.entity.MyUserDetails">
        SELECT
            u.id,
            u.username,
            u.PASSWORD,
            u.enabled,
            u.accountNonExpired,
            u.accountNonLocked,
            u.credentialsNonExpired,
            r.id AS roleId,
            r.NAME,
            r.name_zh
        FROM
            USER AS u
                LEFT JOIN user_role AS rel ON rel.uid = u.id
                LEFT JOIN role AS r ON r.id = rel.rid
        WHERE
            u.username = #{userName}
    </select>
</mapper>
@Mapper
public interface UserDAO {
    /**
     * 查询用户及其用户角色信息
     */
    MyUserDetails loadUserByUsername(@Param("userName") String userName);

    /**
     * 更新密码
     */
    int updatePassword(@Param("username")String username ,@Param("newPassword") String newPassword);
}

@Configuration
public class SecurityWebConfig extends WebSecurityConfigurerAdapter {


    private final MyUserDetailsPasswordService myUserDetailsPasswordService ;
    @Autowired
    public SecurityWebConfig(MyUserDetailsPasswordService myUserDetailsPasswordService) {
        this.myUserDetailsPasswordService = myUserDetailsPasswordService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 这是将UserDetailsService 和 UserDetailsPasswordService 写在一些的配置写法
        auth.userDetailsService(myUserDetailsPasswordService);
        // 是否两个接口分开的写法
//        auth.userDetailsService(userDetailsService()).userDetailsPasswordManager(new UserDetailsPasswordService());

    }
}

以上就是SpringSecurity 的密码加密全部内容!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Secuirty 密码加密认证讲解 的相关文章

  • Linux多线程编程问题:对‘pthread_create’未定义的引用

    在Linux下进行多线程程序测试时出现如下问题 xff1a 对 pthread create 未定义的引用 collect2 error ld returned 1 exit status 问题原因 xff1a linux下调用子线程时会用
  • PROC系列之---/proc/pid/stat

    proc stat 包含了所有CPU活跃的信息 xff0c 该文件中的所有值都是从系统启动开始累计到当前时刻 root 64 localhost cat proc 6873 stat 6873 a out R 6723 6873 6723
  • realsense d435 launch中修改频率不好用

    警告提示 xff1a Given stream configuration is not supported by the device span class token operator span Stream Color Stream
  • RK1109/RK1126--人工智能NPU强劲算力芯片

    瑞芯微电子第四届 开发者之春 大会上 xff0c 针对视觉领域 xff0c 推出全新的视觉处理器RV1109 1126芯片 从下图中我们可以清晰的看出 xff0c 在2020年瑞芯微推出的产品主要是面向物联网人工智能 机器视觉和机顶盒领域
  • Makefile

    Makefile的引入及规则 使用keil mdk avr等工具开发程序时点点鼠标就可以编译了 xff0c 使用Keil xff0c MDK xff0c AVR等工具开发程序时点点鼠标就可以编译了 它的内部机制是什么 它怎么组织管理程序 怎
  • 转载知乎-深度可分离卷积

    深度可分离卷积
  • vgg16网络改深度可分离卷积

    原网络 span class token keyword class span span class token class name CNN0 span span class token punctuation span nn span
  • Dropout 丢弃函数的使用

    Class span class token class name USeDropout span span class token punctuation span nn span class token punctuation span
  • libtorch-resnet18

    与大家分享一下自己在学习使用libtorch搭建神经网络时学到的一些心得和例子 xff0c 记录下来供大家参考 首先我们要参考着pytorch版的resnet来搭建 xff0c 这样我们可以省去不必要的麻烦 xff0c 上代码 xff1a
  • Yolov5 -libtorch部署

    将python训练好的网络模型转为可以再libtorch上走的pth模型 xff0c 转换代码如下 xff1a 可以直接赋值粘贴 import argparse import sys import time sys span class t
  • c++ 关于error LINK2005: XXXX已经在 .obj 中定义“的问题

    代码很多的时候出现这个问题很棘手 xff0c 小号大量时间来排查问题 xff0c 所以一边学习一边记录学习中出现的问题 原因 xff1a 是因为编程习惯的问题 xff0c 直接在头文件 h中直接定义了变量或者函数 xff0c 然后A cpp
  • 使用vs2019将libtorch或者网络打包成dll

    最近在搞一个程序 xff0c 需要把libtorch打包成dll xff0c 让别人使用 xff0c 在网上找了好久都没只有找到合适的答案 xff0c 最后在一个博主大哥那里找到了 xff0c 很是感激这位大哥与我们分享自己的经验 xff0
  • 【无标题】 libtorch C++ vs2017 debug模式可以正确加载模型,release模式错误

    转发 xff1a libtorch C 43 43 vs2017 debug模式可以正确加载模型 xff0c release模式错误 https blog csdn net weixin 43862688 article details 1
  • targetcli

    Linux IO LIO Target is an open source implementation of the SCSI target thathas become the standard one included in the
  • libtorch-加载预训练模型出现No such serialized submodule: ‘xxx‘

    今天在用libtorch训练得时候 xff0c 想用预训练模型加速训练 xff0c 居然报错 xff0c 以为是模型得问题 xff0c 然后重新训练了一个模型 xff0c 作为预训练模型 xff0c 还是报错 xff0c 一时找不到原因 x
  • QT学习之路-记事本

    1 在创建记事本之前先明白有哪些功能 xff1a 先创建一个菜单栏 xff0c 菜单栏是用来装各种功能的一个地方如上图所示 xff0c 文件 编辑所在的地方为菜单栏 xff0c span class token comment 创建菜单栏
  • yolov5-pytorch导出模型问题

    在官网提供的代码中 xff0c 很方便的可以把pytorch的模型转为libtorch的模型 xff0c 但是在转换前要明白自己转换后的模型是仅仅为了推理部署 xff0c 还是说用转换后的模型作为libtorch的预训练模型继续使用呢 xf
  • libtorch与pytorch索引张量值操作([:]与index)

    由于我最近在学习libtorch相关的东西 xff0c 所以就记录一下使用libtorch与pytorch一样对张量操作的语法 下面是我转载的一位大佬的文章 xff0c 这里只做技术探讨 xff0c 不做其他用途 想要学习的可以参考一下大佬
  • QT 报 QMetaObject::connectSlotsByName: No matching signal for on_btn_clicked()

    在QT中 xff0c 自己编写命名信号和槽的时候 xff0c 在用connect的时候报出以下错误 xff1a QMetaObject span class token double colon punctuation span conne
  • CRNN-模型转换问题Missing Errorin loading state_dict for CRNN

    在将CRNN pytorch模型转为libtorch模型的时候出现报错情况 xff0c Missing Errorin loading state dict span class token keyword for span CRNN 96

随机推荐

  • CRNN-libtorch模型推理的时候报错std:runtime_error

    使用libtorch模型推理的时候出现报错std runtime error 这里报错的情况一般是数据不同步的问题 xff0c 也就是说我们的模型是在gpu上 xff0c 而数据是在cpu上 xff0c 那么要做的一件事就是检查forwar
  • 数据集txt格式划分为多个txt文件夹

    简单记录一下数据标签txt格式划分为多个文件 xff0c 通常我们标注号的标签 xff0c 都是在一个txt文件夹中 xff0c 我们训练的时候需要把txt中的标签按照一定的比例划分为多个文件 xff0c 这里贴出划分为三个文件的代码 xf
  • 租用终端训练网络遇到的一些坑

    最近由于电脑配置和经济的问题 xff0c 想训练模型 xff0c 无奈只能选择在平台上训练了 xff0c 我使用的是AutoDL这个平台 xff0c 感觉还行 xff0c 还是挺划算 感兴趣或者需要的老铁可以点击蓝色字体进去尝试一下 接下来
  • CRNN-pytorch模型转libtorch模型踩坑记录

    这段时间一直在做CRNN文字识别的问题 xff0c 从pytorch中训练好的模型然后转到libtorch中去 xff0c 但是CRNN提供的代码没有转libtorch模型的部分 xff0c 于是就在网上到处乱找 xff0c 其中找到了这篇
  • 如何升级gcc版本

    下面将整个过程更新的过程写下来 xff0c 希望对有需要的人提供一些帮助 首先需要准备需要材料 xff1a gcc4 4 2版需要安装gmp4 2 0 43 和mpfr2 3 0 43 xff0c 到GMP的网站 xff08 http gm
  • 召回率与精确率的理解

    写在前面 识别精度主要由召回率 xff08 recall xff09 和精确率 xff08 precision xff09 两个指标决定 xff0c 在训练结束时可以通过re pre曲线来表示模型的准确度 xff0c 也可以根据二者之间的关
  • vs常见的错误集锦-error C4996: ‘wcstombs‘: This function or variable may be unsafe

    问题所在 xff1a 缺少宏定义 在使用wcstombs这个函数时遇到了题目所说的这个情况 xff0c 查找得知是缺少宏定义 xff0c 按照网上查找的问题 xff0c 在vs的配置中添加宏定义就行了 xff1b 在以下的位置 xff1a
  • Keil左侧Function列表无法显示(已解决)

    左侧的Functions框框会显示所有的库函数 xff0c 方便查找 查找的来源是工程所在的目录 如果把目录放得太深 xff0c 就会导致扫描不出来 在工程文件里面并列新建一个LIB文件夹用来存放 xff0c 把Inc和Src放进去 打开F
  • Linux服务器配置ulimit的常用参数介绍

    最近在小鸟云配置了一个Linux服务器 xff0c 实例是debian 7 5 系统 xff0c 在进行系统优化的过程中遇到一些有关Ulimit的事项 xff0c 整理了相关的参数介绍和配置介绍 xff0c 有需要可以简单看看 Ulimit
  • 【视觉检测C++接口实现】vs2019使用动态链接库yolo_cpp_dll调用yolov3

    目录 0 前言 1 准备工作 1 1 yolo cpp dll dll和yolo cpp dll lib的获取 1 2 pthreadGC2 dll和pthreadVC2 dll的获取 1 3 yolo v2 class hpp的获取 1
  • 【jetson nano】在ubuntu18.04下,c++调用链接库实现yolov3

    目录 0 前言 1 下载安装opencv 3 4 0 1 1 配置相应的以来库 1 2 下载opencv 3 4 0 xff08 源码 xff09 1 3 编译 xff08 时间较长 xff09 1 4 安装 1 5 配置opencv路径
  • 51单片机寄存器篇

    以下依次为IE IP TMOD TCON SCON寄存器结构 xff1a B7B6B5B4B3B2B1B0EA ET2ESET1EX1ET0EX0 B7B6B5B4B3B2B1B0 PT2PSPT1PX1PT0PX0 B7B6B5B4B3B
  • 单片机蓝桥杯——串口通信

    1 什么是串行 并行 单工 全双工 半双工 同步 异步 通讯的方式分类 xff1a 并行通信 串行通信 并行通信 xff1a 数据的各位同时在多根数据线上发送或接收 串行通信 xff1a 数据的各位在同一根数据线上逐位发送和接收7 并行通信
  • 串口、UART、USART、COM、USB、TTL、RS232、RS485、RS422简介

    串口 COM口 USB口是指的物理接口形式 xff08 硬件 xff09 xff1b TTL RS 232 RS 485 USB电平是指的电平标准 xff08 电信号 xff09 串口 UART口 USART口 COM口 USB口 xff0
  • 无线收发模块——NRF24L01

    1 什么是nRF24L01 nRF24L01是由NORDIC生产的工作在2 4GHz 2 5GHz的ISM 频段的单片无线收发器芯片 有着极低的电流消耗 nRF24L01与5V单片机的连接通过SPI接口进行通讯 xff0c 输出功率频道选择
  • 使用 monitor command 监控 QEMU 运行状态

    使用 monitor command 监控 QEMU 运行状态 在虚拟化的研究领域 xff0c QEMU 有着举足轻重的地位 2007 年 2 月发布的 Linux 2 6 20 内核中 xff0c 集成了 KVM 作为其虚拟化的具体实现
  • 基于STM32的多普勒雷达测速

    基于多普勒雷达传感器 xff0c 以STM32单片机为主控芯片 xff0c 根据不同模块检测距离的不同 xff0c 使用不同多普勒雷达传感器实现对远近距离车辆行驶速度及方向的测量 1 基础知识 雷达 雷达英文为Radar xff0c Rad
  • 语音合成芯片——SYN6658

    一 SYN6658 SYN6658是中文语音合成芯片 xff0c 通过UART 接口或SPI 接口通讯方式 xff0c 接收待合成的文本数据 xff0c 实现文本到语音的转换 可以采用GB2312 GBK BIG5 和Unicode 四种编
  • c++学习笔记(一)新手区分C语言、C++、VC++

    我认为第一件事需要跟各位说清楚的就是C语言和C 43 43 以及VC 43 43 之间的区别 特别是许多朋友一开始就喜欢下载使用VS xff08 Visual Studio xff09 xff0c 所以我认为这很有必要跟大家说清楚 xff0
  • Spring Secuirty 密码加密认证讲解

    目录 一 密码加密介绍 1 1 常见加密的策略 1 Hash 算法 2 单向自适应函数 二 Security加密结构 2 1 PasswordEncoder 2 2 密码认证流程 2 3 DeletaingPasswordEncoder 1