spring security中的密碼加密:BCrypt算法工具類BCryptPasswordEncoder

  spring security中有多種密碼加密方式,MD5算法的Md5PasswordEncoder、SHA 算法的ShaPasswordEncoder,但由於是弱加密算法,都被棄用了。推薦使用的是BCrypt算法的BCryptPasswordEncoder。

一、BCryptPasswordEncoder的使用

(一)添加依賴

  在SpringBoot項目中加入spring security依賴

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

(二)放行請求

  添加了spring security依賴後,所有的請求都被spring security所控制了,這裏只是使用BCrypt密碼加密的部分,所以需要編寫配置類,配置爲所有地址都可以匿名訪問。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @author chushiyan
 * @email  Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
 * @description
 */

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/**").permitAll()
            .anyRequest().authenticated()
            .and().csrf().disable();
    }
}

(三)啓動類中配置bean

    @Bean
    public BCryptPasswordEncoder getBcryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

(四)加密密碼

// 加密密碼
user.setPassword(bCryptPasswordEncoder.encode(password));

(五)校驗密碼

// 參數一:待檢驗的、未加密的密碼
// 參數二:從數據庫中查詢出的加密後密碼
bCryptPasswordEncoder.matches(password, userFromDB.getPassword())

二、深入瞭解BCryptPasswordEncoder

(一)測試生成密碼

/**
 * @author chushiyan
 * @email  Y2h1c2hpeWFuMDQxNUAxNjMuY29t(base64)
 * @description
 */
@SpringBootTest
class ApplicationTests {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Test
    public void testBCryptPasswordEncoder() {
        for (int i = 0; i < 10; i++) {
            String password = "123456";
            String hashed = bCryptPasswordEncoder.encode(password);
            System.out.println(hashed);
        }
    }
}

  控制檯輸出:

$2a$10$A/Jty.uPopRKNL/Pagnhvufb9sPScp74h93qHGxFztBlrzdOJU66a
$2a$10$I4q0m0Tesq5GRLETEyXOPObHaI8JYGohK1m/63KtAKjRjHws1.Fi.
$2a$10$ByPK1poz.JRGSlO/F9CiqexXW2VEgeaScjuQPLPqksLRGv8xtd5uy
$2a$10$vs3Vj7BiQGRnjIWq895CXunLUyDAVRrZccJR/ggMy/nWAiklUxXJC
$2a$10$4LKrbmr4u7q71yPq9PZLxOkCUCSo1Q.o73nfTXauIDCoKBMoFs7vG
$2a$10$Z5VD7fjGmze05VuWMJxVIuPXXO77YIFDVUi/XYQPnb6G3t8mikPJm
$2a$10$T39UcqdG73nfHLiqzYz.tOtTk7efiFUqmaqxew6xHL9gsBgFmpvCi
$2a$10$9VhF9phPI6VKSpy2ne3AteBfCZUBpWEkJoEh2uaGO.yONcl.fmP.2
$2a$10$gZv6eWEQ/TYwwHQJ1Hmex.v8XvcpzzyjIaoWjGOapYLanMMhrYBNW
$2a$10$ZVH0p2D0xRJ2CBIaWzdF5eT.4TKpSwDM7wP/IA4Qbv8u7lzOL7ipe

  爲什麼密碼都是123456,而加密後的結果不一樣?因爲BCryptPasswordEncoder中的encode()內部調用BCrypt類隨機生成了鹽(salt),加了不同的鹽進行hash自然不一樣。

(二)詳解加密後的密碼

$2a$10$A/Jty.uPopRKNL/Pagnhvufb9sPScp74h93qHGxFztBlrzdOJU66a

加密後的密碼長度爲60(所以設計數據庫時得保證該字段長度不小於60)

說明
$ 分割符
$2a BCrypt加密算法版本,在BCryptPasswordEncoder類內部定義了一個枚舉類,枚舉了3個加密算法版本:
public enum BCryptVersion {
$2A("$2a"),
$2Y("$2y"),
$2B("$2b");
可以通過構造函數指定版本:public BCryptPasswordEncoder(BCryptVersion version)
如:new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2A);
$10 表示10次循環加鹽salt。默認10次,最少4次,最多31次。
可以通過構造函數指定次數:public BCryptPasswordEncoder(int strength)
10$之後的22位 鹽。BCryptPasswordEncoder內部調用BCrypt的gensalt()方法隨機生成
最後的31位 明文密碼password和鹽hash後的值

三、非SpringBoot項目使用BCrypt加密算法

  BCrypt是一個算法,各個語言都有自己的實現。在java中有jBCrypt,spring security中也實現了BCrypt算法(沒有依賴jBCrypt)。
  如果不是SpringBoot項目,就可以使用jBCrypt。

  jBCrypt官網

  官網示例:

// Hash a password for the first time
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());

// gensalt's log_rounds parameter determines the complexity
// the work factor is 2**log_rounds, and the default is 10
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));

// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
	System.out.println("It matches");
else
	System.out.println("It does not match");

導包:

        <dependency>
            <groupId>org.mindrot</groupId>
            <artifactId>jbcrypt</artifactId>
            <version>0.4</version>
        </dependency>

或者加入jbcrypt-0.4.jar(這個包其實就BCrypt.java這一個類)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章