Spring Security系列教程之SpringSecurity中的密码加密

本文介绍了Spring Security的密码加密机制,重点讲解了散列加密和Spring Security的三种密码处理方案,包括BCryptPasswordEncoder的使用。通过代码示例展示了如何利用BCryptPasswordEncoder进行密码加密,以及如何在Spring Security中实现多密码加密方案共存。
摘要由CSDN通过智能技术生成

前言

截止到现在,一一哥已经带各位学习了很多关于SpringSecurity的知识点,但是Spring Security作为一个安全框架,其中必然就应该带有安全加密方面的内容,所以本篇文章,一一哥 就带各位来学习Spring Security中的密码加密机制。

Let's go!

图片

一. 密码加密简介

1. 散列加密概述

我们开发时进行密码加密,可用的加密手段有很多,比如对称加密、非对称加密、信息摘要等。在一般的项目里,常用的就是信息摘要算法,也可以被称为散列加密函数,或者称为散列算法、哈希函数

这是一种可以从任何数据中创建数字“指纹”的方法,常用的散列函数有 MD5 消息摘要算法、安全散列算法(Secure Hash Algorithm)等

2. 散列加密原理

散列函数通过把消息或数据压缩成摘要信息,使得数据量变小,将数据的格式固定下来,然后将数据打乱混合,再重新创建成一个散列值,从而达到加密的目的。

散列值通常用一个短的随机字母和数字组成的字符串来代表,一个好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理时,如果我们不抑制冲突来区别数据,会使得数据库中的记录很难找到。

但是仅仅使用散列函数还不够,如果我们只是单纯的使用散列函数而不做特殊处理,其实是有风险的!比如在两个用户密码明文相同时,生成的密文也会相同,这样就增加了密码泄漏的风险。

所以为了增加密码的安全性,一般在密码加密过程中还需要“加盐”,而所谓的“盐”可以是一个随机数,也可以是用户名。”加盐“之后,即使密码的明文相同,用户生成的密码密文也不相同,这就可以极大的提高密码的安全性。

传统的加盐方式需要在数据库中利用专门的字段来记录盐值,这个字段可以是用户名字段(因为用户名唯一),也可以是一个专门记录盐值的字段,但这样的配置比较繁琐。

3. Spring Security中的密码处理方案

那么在Spring Security中,对密码是怎么进行处理的呢?其实Spring Security对密码的处理方案,有如下3种方式:

  • 对密码进行明文处理,即不采用任何加密方式;

  • 采用MD5加密方式;

  • 采用哈希算法加密方式。

4. BCryptPasswordEncoder简介

以上说的是3种密码处理方案,并不代表只有3种加密算法,这个请大家注意哦!

实际上,Spring Security提供了多种密码加密算法,但官方推荐使用的是BCrypt Password Encoder方案,如下图所示:

图片

我们开发时,用户表中的密码通常是使用MD5等不可逆算法加密后存储,但为了防止彩虹表破解,可以先使用一个特定的字符串(如域名)进行加密,然后再使用一个随机的salt(盐值)加密。其中特定的字符串是程序代码中固定的,salt是每个密码单独随机的,我们一般会给用户表加一个字段单独存储,但这样比较麻烦。

而BCrypt算法却可以随机生成salt并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt。不同于 Shiro 中需要自己处理密码加盐,在 Spring Security 中,BCrypt Password Encoder 本身就自带了盐,所以处理起来非常方便。

另外BCryptPasswordEncoder使用BCrypt强哈希函数,我们在使用时可以选择提供strength和SecureRandom参数。strength值(取值在4~31之间,默认为10)越大,则密钥的迭代次数就越多,密钥迭代次数为2^strength。

二. 利用BCryptPasswordEncoder进行加密

了解了这些基本的理论知识之后,壹哥 就带各位进行代码实现啦。

我们继续在之前的案例基础之上进行本案例的代码实现,所以项目创建过程略过,请参考之前的章节内容。

1. 编写register接口

为了方便测试,我们首先在UserController中编写一个register接口,用于注册一个新用户,在添加用户时对密码进行加密。

    @Autowired
    private PasswordEncoder passwordEncoder;

 /**
     * 添加用户.这里我们采用表单形式传参,传参形式如下:
     * http://localhost:8080/user/register?username=test&password=123
     */
    @GetMapping("/register")
    public User registerUser(@RequestParam(required = false) User user){
        user.setEnable(true);
        user.setRoles("ROLE_ADMIN");

        //对密码进行加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));

        userMapper.addUser(user);

        return user;
    }

别忘了注入PasswordEncoder对象!

2. 配置密码加密算法

接下来我们在Security Config配置类中,配置到底该采用哪种密码加密算法。我们在Spring Boot环境中是非常容易实现加密算法配置的,只需要创建一个Password Encoder对象即可。

@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                //放行register接口
                .antMatchers("/user/register")
                .permitAll()
                .antMatchers("/user/**")
                .hasRole("USER")
                .antMatchers("/app/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                //对跨域请求伪造进行防护---->csrf:利用用户带有登录状态的cookie进行攻击的手段
                .csrf()
                .disable();
    }

    //配置采用哪种密码加密算法
    @Bean
    public PasswordEncoder passwordEncoder() {
        //不使用密码加密
        //return NoOpPasswordEncoder.getInstance();

        //使用默认的BCryptPasswordEncoder加密方案
        return new BCryptPasswordEncoder();

        //strength=10,即密钥的迭代次数(strength取值在4~31之间,默认为10)
        //return new BCryptPasswordEncoder(10);

        //利用工厂类PasswordEncoderFactories实现,工厂类内部采用的是委派密码编码方案.
        //return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

}

注意:这里我们可以有

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值