Google Code Prettify

2018年8月14日 星期二

Spring Security: 密碼加密

這年頭網站的密碼不太可能會以明碼儲存,或是以對稱加密的方式加密後儲存,這就不多說了 … spring security 5.x 提供不少非對稱加密的演算法 bcrypt、MD5、SHA-1、SHA-256 … 預設是 bcrypt。看一下底下程式,應該就可以初步了解怎麼加密、比對。
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,並把要使用的加密演算法及其代碼傳入。

回過頭來看上面輸出的結果,同樣加密 "abcdefg",bcrypt1、bcrypt2 輸出的字串並不一樣,事實上每次加密都不會一樣,所以,比對密碼是否相同不能直接用 equals 比對,而要用PasswordEncoder 提供的 matches() method,第一個參數傳入明碼的密碼,第二個參數則傳入要比對的加密後的密碼字串,這樣就可以傳回 true (相同) 或 false (不同)。

沒有留言:

張貼留言