接下來幾個章節,將逐個介紹身份驗證流程中主要介面
| 介面 | 描述 |
|---|---|
| UserDetails | 代表SpringSecurity所看到的用戶 |
| GrantedAuthority | 定義應用程式目的范圍內允許用戶執行的操作(讀、寫、洗掉等) |
| UserDetailsService | 表示用于按用戶名檢索用戶詳細資訊的物件 |
| UserDetailsManager | 一個較為特殊的UserDetailsService介面,除了按用戶名檢索用戶外,它還可以用于更改用戶集合或特定用戶 |
| PasswordEncoder | 指定如何對密碼進行加密或哈希化,以及檢查給定的已編碼字串是由與明文密碼匹配 |
本文將一起學習相對獨立的PasswordEncoder,
一、先看看定義
package org.springframework.security.crypto.password;
/**
* Service interface for encoding passwords.
*
* The preferred implementation is {@code BCryptPasswordEncoder}.
*
* @author Keith Donald
*/
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;
}
}
該介面定義了兩個抽象方法,其中幾個具有默認實作,在處理PasswordEncoder實作時,最常見的是抽象的encode()和matches()方法,
encode(CharSequence rawPassword)方法的目的是回傳所提供字串的轉換,就SpringSecurity功能而言,它用于為指定密碼提供加密或哈希化,
之后可以使用matches(CharSequence rawPassword, String encodedPassword)方法檢查已編碼的字串是否與演示密碼匹配,可以在身份驗證程序中使用matches()方法根據一組已知憑據來檢驗所提供的的密碼,
第三個方法被稱為upgradeEncoding(String encodedPassword),在介面中默認設定為false,如果重寫它以回傳true,那么為了更好的安全性,將重新對已編碼的密碼進行編碼(不推薦這種方式),
二、介面的作用
一般而言,系統并不以明文形式管理密碼,因此密碼通常要經過某種轉換,這使得讀取和竊取密碼變得較為困難,為此,SpringSecurity定義了一個單獨的介面,
實作這個介面是為了告知SpringSecurity如何驗證用戶的密碼,在身份驗證程序中,PasswordEncoder會判定密碼是否有效,每個系統都會存盤以某種方式編碼過的密碼,最好把密碼哈希化存盤起來,這樣別人就不會讀到明文密碼了,PasswordEncoder還可以對密碼進行編碼,介面宣告的encode()和matches()方式實際上是對其職責的定義,這兩個方法都是同一介面的一部分,因此它們緊密相連,應用程式對密碼進行編碼的方式與驗證密碼的方式相關,
三、實作PasswordEncoder
3.1 使用默認的PasswordEncoder
在 Spring Security 5.0 之前,PasswordEncoder 默認值是 NoOpPasswordEncoder,這需要純文本密碼, 但現在您可能期望現在的默認值類似于BCryptPasswordEncoder,但是,這忽略了三個現實世界的問題:
- 許多應用程式使用無法輕松遷移的舊密碼編碼,
- 密碼存盤的最佳做法將再次更改,
- 作為一個框架,Spring 安全性不能經常進行重大更改,
相反,Spring Security 引入了 DelegatingPasswordEncoder,它通過以下方式解決了所有問題:
- 確保使用當前密碼存盤建議對密碼進行編碼
- 允許以現代和傳統格式驗證密碼
- 允許將來升級編碼
您可以使用PasswordEncoderFactories輕松構造DelegatingPasswordEncoder 的實體:
PasswordEncoder passwordEncoder =
PasswordEncoderFactories.createDelegatingPasswordEncoder();
當然也可以選擇其它實體:
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);
3.2 使用自定義的的PasswordEncoder
通常情況下,使用spring boot security自帶的password encoder已經足夠滿足使用場景了,筆者也不建議自己實作password encoder,
3.3 注入PasswordEncoder
在開發中,我們將 BCryptPasswordEncoder 的實體放入Spring容器即可
//密碼編碼器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543215.html
標籤:其他
