PasswordEncoder encoder1 = PasswordEncoderFactories.createDelegatingPasswordEncoder();
String encryption1 = encoder1.encode("abcdefg");
System.out.println("bcrypt1:" + encryption1);
String encryption2 = encoder1.encode("abcdefg");
System.out.println("bcrypt2:" + encryption2);
PasswordEncoder encoder2 = new BCryptPasswordEncoder();
boolean result = encoder2.matches("abcdefg", "$2a$10$aKFYCaH2bRMeIB.FBAWC6.NcsEF.yR.3FXm/ZhIULLDudtXnMQ/Ni");
System.out.println("比較結果: " + result);
bcrypt1:{bcrypt}$2a$10$ZiYiw5U397Zr3ORAc/NrbutwH2p5YqzlE/Ugk34oCW6/s2LloIjWy
bcrypt2:{bcrypt}$2a$10$2UcGko8JuZ4Xze/jqv17yeAxhALhIyU/Usx4uKXHTe6D.e/vUHrq6
比較結果: true
再來看一下程式,PasswordEncoderFactories 是 spring security 提供的工廠類別,可以產生一個 DelegatingPasswordEncoder 類別的物件,預設是用 bcrypt 演算法,如果我們想用其它演算法呢? 官網的 Docs 提供了如下的方法:
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);
這個官方的範例,簡單的就是 new 一個 DelegatingPasswordEncoder,並把要使用的加密演算法及其代碼傳入。Map
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);
回過頭來看上面輸出的結果,同樣加密 "abcdefg",bcrypt1、bcrypt2 輸出的字串並不一樣,事實上每次加密都不會一樣,所以,比對密碼是否相同不能直接用 equals 比對,而要用PasswordEncoder 提供的 matches() method,第一個參數傳入明碼的密碼,第二個參數則傳入要比對的加密後的密碼字串,這樣就可以傳回 true (相同) 或 false (不同)。