Spring Security灵活的PasswordEncoder加密方式解析

 更新时间:2023年09月18日 14:12:47   作者:恒宇少年  
这篇文章主要介绍了Spring Security灵活的PasswordEncoder加密方式解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

导读

本章基于Spring Security 5.4.1版本编写,从5.x版本开始引入了很多新的特性。

为了适配老系统的安全框架升级,Spring Security也是费劲了心思,支持不同的密码加密方式,而且根据不同的用户可以使用不同的加密方式。

构建Spring Security项目

Spring Security的集成使用还是很简单的,根据项目使用的框架不同大致分为两种集成方式:

SpringBoot方式集成

SecurityBom方式集成

SpringBoot方式构建

pom.xml文件内添加如下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

SecurityBom方式构建

spring-security-bom是一个提供了Spring Security指定版本的全部默认依赖的pom类型项目,我们可以通过dependencyManagement进行配置到项目中,这样我们就可以直接添加对应的dependency了(注意:版本号因为bom已经注定,所以dependency不需要指定.)。

pom.xml文件内添加如下内容:

<dependencies>
  // ...省略其他依赖
  <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-core</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
  </dependency>
</dependencies>
<dependencyManagement>
  <dependencies>
    <!--配置SecurityBom-->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-bom</artifactId>
        <version>5.4.1</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

注意事项:我们构建Web类型的安全项目时,spring-security-configspring-security-corespring-security-web三个依赖都是必须添加的。

PasswordEncoder

PasswordEncoderSpring Security提供的密码加密方式的接口定义,源码类如下所示:

public interface PasswordEncoder {
    /**
     * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
     * greater hash combined with an 8-byte or greater randomly generated salt.
     */
    String encode(CharSequence rawPassword);
    /**
     * Verify the encoded password obtained from storage matches the submitted raw
     * password after it too is encoded. Returns true if the passwords match, false if
     * they do not. The stored password itself is never decoded.
     *
     * @param rawPassword the raw password to encode and match
     * @param encodedPassword the encoded password from storage to compare with
     * @return true if the raw password, after encoding, matches the encoded password from
     * storage
     */
    boolean matches(CharSequence rawPassword, String encodedPassword);
    /**
     * Returns true if the encoded password should be encoded again for better security,
     * else false. The default implementation always returns false.
     * @param encodedPassword the encoded password to check
     * @return true if the encoded password should be encoded again for better security,
     * else false.
     */
    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}
  • #encode

    该方法提供了明文密码的加密处理,加密后密文的格式主要取决于PasswordEncoder接口实现类实例。

  • #matches

    匹配存储的密码以及登录时传递的密码登录密码是经过加密处理后的字符串)是否匹配,如果匹配该方法则会返回true.

内置的PasswordEncoder实现列表

NoOpPasswordEncoder(已废除)

明文密码加密方式,该方式已被废除(不建议在生产环境使用),不过还是支持开发阶段测试Spring Security的时候使用。

BCryptPasswordEncoder

Argon2PasswordEncoder

Pbkdf2PasswordEncoder

SCryptPasswordEncoder

DelegatingPasswordEncoder

在之前版本集成Spring Secuirty时,我们需要通过@Bean的方式来配置全局统一使用的密码加密方式(PasswordEncoder),当然这种方式现在还是适用的,不过在5.x版本开始为了支持动态的多种密码加密方式,DelegatingPasswordEncoder委托加密方式类应用而生,它内部其实是一个Map集合,根据传递的Key(Key为加密方式)获取Map集合的Value,而Value则是具体的PasswordEncoder实现类。

DelegatingPasswordEncoder建立密码格式的规则,格式如:{bcrypt}encodePassword,示例如下所示:

// {bcrypt}格式会委托给BCryptPasswordEncoder加密类
{bcrypt}$2a$10$iMz8sMVMiOgRgXRuREF/f.ChT/rpu2ZtitfkT5CkDbZpZlFhLxO3y
// {pbkdf2}格式会委托给Pbkdf2PasswordEncoder加密类
{pbkdf2}cc409867e39f011f6332bbb6634f58e98d07be7fceefb4cc27e62501594d6ed0b271a25fd9f7fc2e
// {MD5}格式会委托给MessageDigestPasswordEncoder加密类
{MD5}e10adc3949ba59abbe56e057f20f883e
// {noop}明文方式,委托给NoOpPasswordEncoder
{noop}123456
// ...

指定用户使用PasswordEncoder

DelegatingPasswordEncoder是默认的PasswordEncoder加密方式,所以我们可以为不同的用户配置所使用不同的密码加密方式,只需要密码格式按照:{away}encodePassword来进行持久化即可。

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()
                .and()
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/**")
                .authenticated();
    }
    @Bean
    public UserDetailsService users() {
        // {MD5}value必须大写,value值必须是32位小写
        // admin
        UserDetails admin = User.builder()
                //.passwordEncoder(encoder::encode)
                .username("admin").password(
                        "{MD5}e10adc3949ba59abbe56e057f20f883e"
                ).roles("admin").build();
        // hengboy
        UserDetails hengboy = User.builder()
                .username("hengboy")
                .password("{bcrypt}$2a$10$iMz8sMVMiOgRgXRuREF/f.ChT/rpu2ZtitfkT5CkDbZpZlFhLxO3y")
                .roles("admin")
                .build();
        // yuqiyu
        UserDetails yuqiyu = User.builder().username("yuqiyu")
                //.password("{noop}123456")
                .password("{pbkdf2}cc409867e39f011f6332bbb6634f58e98d07be7fceefb4cc27e62501594d6ed0b271a25fd9f7fc2e")
                .roles("user").build();
        return new InMemoryUserDetailsManager(admin, yuqiyu, hengboy);
    }
}

上面是使用内存方式存储安全用户的实现代码,在创建UserDetailsService类的实例时将用户列表通过构造参数进行传递。

所创建的用户:admin,采用MD5的加密方式进行密码编码,这里需要注意的是MD5加密后的字符串必须为小写32位

所创建的用户:hengboy,采用bcrypt方式进行密码编码。

所创建的用户:yuqiyu,采用pbkdf2方式进行密码编码。

覆盖默认的PasswordEncoder

Spring Security 5.x版本默认的PasswordEncoder方式改成了DelegatingPasswordEncoder委托类,不过如果是通过PasswordEncoderFactories#createDelegatingPasswordEncoder方法创建的DelegatingPasswordEncoder实例时,默认其实使用的还是BCryptPasswordEncoder,源码如下所示:

public static PasswordEncoder createDelegatingPasswordEncoder() {
  String encodingId = "bcrypt";
  Map<String, PasswordEncoder> encoders = new HashMap<>();
  encoders.put(encodingId, new BCryptPasswordEncoder());
  // 省略...
  return new DelegatingPasswordEncoder(encodingId, encoders);
}

如果我们项目中不需要使用DelegatingPasswordEncoder委托密码编码方式,可以通过@Bean的方式来统一配置全局共用的PasswordEncoder,如下所示:

@Bean
public PasswordEncoder passwordEncoder() {
  return new BCryptPasswordEncoder();
}

可以根据项目自行选择所使用的PasswordEncoder实现类。

以上就是Spring Security灵活的PasswordEncoder加密方式解析的详细内容,更多关于Spring Security PasswordEncoder加密的资料请关注脚本之家其它相关文章!

相关文章

  • SpringMVC 拦截器的使用示例

    SpringMVC 拦截器的使用示例

    这篇文章主要介绍了SpringMVC 拦截器的使用示例,帮助大家更好的理解和学习使用SpringMVC,感兴趣的朋友可以了解下
    2021-04-04
  • Java在枚举类型中增加自定义方法详解

    Java在枚举类型中增加自定义方法详解

    这篇文章主要介绍了Java在枚举类型中增加自定义方法详解,对于枚举类型来说,除了无法继承它以外,基本可以将它看作一个普通的类,这意味着你可以在里面增加自定义的方法,甚至可以增加一个 main() 方法,需要的朋友可以参考下
    2023-11-11
  • Java中通过继承Thread类创建线程的步骤

    Java中通过继承Thread类创建线程的步骤

    本文介绍了如何通过继承Thread类创建线程,包括Thread类的定义、创建线程的步骤、优缺点、使用场景和注意事项,通过示例代码展示了多线程下载文件的实现,感兴趣的朋友跟随小编一起看看吧
    2025-02-02
  • swagger文档增强工具knife4j使用图文详解

    swagger文档增强工具knife4j使用图文详解

    这篇文章主要介绍了swagger文档增强工具knife4j使用详解,想要使用knife4j非常简单,只要在Springboot项目中引入knife4j的依赖即可,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • Ireport的安装与使用教程

    Ireport的安装与使用教程

    这篇文章主要介绍了Ireport的安装与使用教程,需要的朋友可以参考下
    2021-10-10
  • Springboot集成knife4j实现风格化API文档

    Springboot集成knife4j实现风格化API文档

    这篇文章主要介绍了Springboot如何集成knife4j实现风格化API文档,帮助大家更好的使用springboot框架,感兴趣的朋友可以了解下
    2020-12-12
  • Java 精炼解读时间复杂度与空间复杂度

    Java 精炼解读时间复杂度与空间复杂度

    对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间,这篇文章主要给大家介绍了关于Java时间复杂度、空间复杂度的相关资料,需要的朋友可以参考下
    2022-03-03
  • Java数据溢出代码详解

    Java数据溢出代码详解

    这篇文章主要介绍了Java数据溢出的相关内容,包括具体代码示例,分析比较详细,希望对大家有所帮助,感兴趣的朋友可以参考下。
    2017-09-09
  • SpringBoot如何实现一个实时更新的进度条的示例代码

    SpringBoot如何实现一个实时更新的进度条的示例代码

    本文详细的介绍了SpringBoot如何实现一个实时更新的进度条,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • eclipse创建项目没有dynamic web的解决方法

    eclipse创建项目没有dynamic web的解决方法

    最近上课要用到eclipse,要用到Dynamic web project.但是我下载的版本上没有.接下来就带大家了解 eclipse创建项目没有dynamic web的解决方法,文中有非常详细的图文示例,需要的朋友可以参考下
    2021-06-06

最新评论