欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Security如何實現升級密碼加密方式詳解

 更新時間:2023年01月04日 11:45:48   作者:bangiao  
這篇文章主要為大家介紹了Spring?Security實現升級密碼加密方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

本章內容

  • 密碼加密方式怎么升級?
  • spring security底層怎么實現的密碼加密方式升級?

密碼加密方式怎么升級?

前面我們學過DelegatingPasswordEncoder類,但是不清楚他到底是做什么的,我也沒講的很清楚。所以呢,我們就重新再講一講它的另一個實際應用。

小明呢,有一天在刷新聞。突然收到了一篇關于MD5加密存在重大漏洞的報告, 而最佳的代替加密方案是BCrypt。此時小明慌了。

因為他項目里面就是用著MD5加密。那現在怎么辦呢?小明的用戶體量比較大,你不可能叫客戶/程序員一個個去改是吧?

spring security就提供了一種這種情況的解決方案。

在用戶登錄你的賬戶時,自動的升級您的密碼加密方式。比如說從MD5加密方式變成BCrypt

但是呢,這種方式有一個前提。您數據庫的用戶密碼必須要有ID,也就是花括號的那一部分{noop}123456。

當然如果花括號沒有,然后數據體量就比較大,你只能重寫DelegatingPasswordEncoder。

抄代碼的地方就在PasswordEncoderFactories#createDelegatingPasswordEncoder, 也就是你數據庫中的密碼沒有花括號部分(拿不到ID)的情況下, 使用BCryptPasswordEncoder

小白: "那在spring security中哪一部分定義了這項功能?"

升級方案源碼

首先我們得思考。什么情況下才會進行密碼升級?

按照常理來說,應該是在用戶登錄成功之后進行密碼升級。所以我們在找源碼的時候,應該先去找認證成功的那部分源碼,絕對能找到這部分功能。

我第一反應找UsernamePasswordAuthenticationFilterAbstractAuthenticationProcessingFilter抽象類的doFilter方法

但是不幸的是這里找不到我們想要的功能。所以我立即反應起來這項功能應該是在認證器這邊。

DaoAuthenticationProviderAbstractUserDetailsAuthenticationProvider

找到的認證成功之后,他執(zhí)行的一段函數??梢悦黠@的看出有更新密碼的過程。

這里只要保證upgradeEncoding == true,那么就可以進入更新密碼的過程。

這里我們看到了一段代碼this.userDetailsPasswordService, 可以百分百確定,我們的功能就在這個接口里面。

至于if的另一個函數upgradeEncoding, 你只要知道用戶輸入密碼和數據庫密碼ID不同就為 true, 相同就為 false, 當然還有ID相同不同長度的解決方案, 這里就不細談了

public interface UserDetailsPasswordService {
   UserDetails updatePassword(UserDetails user, String newPassword);
}

如果你英文能力比較強的話,可以直接去查看這個接口上面就會有注釋,內容就是修改用戶名的密碼就這么簡單。

既然已經知道這個接口的存在了,那現在的問題是怎么讓spring security調用我們所實現的這個接口呢?

我現在羅列出三張圖片。就可以從這三張圖片中總結出三種加載我們實現類的方法。

實戰(zhàn)

第一種方式: Spring Bean

public class UserService1 implements UserDetailsService {
	@Resource
	private UsersMapper usersMapper;
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		Optional<Users> optionalUsers = Optional.ofNullable(usersMapper.loadUserByUsername(username));
		return optionalUsers.orElseThrow(() -> new UsernameNotFoundException("找不到用戶名"));
	}
}
@Bean
public UserService1 userService1() throws Exception {
    return new UserService1();
}

這種方式對應著上面第3張圖。

那現在就會有人問的。我并沒有寫出從MD5加密方式升級到BCrypt加密方式。他是怎么自動升級到BCrypt加密方式的?

帶著問題看源碼

他是怎么自動升級到BCrypt加密方式的?

我們知道spring security里面默認使用的PasswordEncoder是這樣的。

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

不知道當做知道哈

他們內部的源碼是這樣的。

public static PasswordEncoder createDelegatingPasswordEncoder() {
    // 省略了一堆代碼
   String encodingId = "bcrypt";
   Map<String, PasswordEncoder> encoders = new HashMap<>();
   encoders.put(encodingId, new BCryptPasswordEncoder());
   encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
   encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
   return new DelegatingPasswordEncoder(encodingId, encoders);
}

嗯,你要注意這幾行代碼。

String encodingId = "bcrypt";
encoders.put(encodingId, new BCryptPasswordEncoder());
return new DelegatingPasswordEncoder(encodingId, encoders);

別的什么都不看,只看encodingId變量。我們現在進入DelegatingPasswordEncoder的內部看看他的構造函數。

public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder,
      String idPrefix, String idSuffix) {
    // 省略一堆代碼
   this.idForEncode = idForEncode;
   this.passwordEncoderForEncode = idToPasswordEncoder.get(idForEncode);
   this.idToPasswordEncoder = new HashMap<>(idToPasswordEncoder);
   this.idPrefix = idPrefix;
   this.idSuffix = idSuffix;
}

encodingId在這個類中被叫做idForEncode

了解了這個之后,再關注這幾行代碼。

this.idForEncode = idForEncode;
this.passwordEncoderForEncode = idToPasswordEncoder.get(idForEncode);

是不是相當于

this.idForEncode = "bcrypt";
this.passwordEncoderForEncode = new BCryptPasswordEncoder();

我們再回到這里看紅框框的這行代碼。

@Override
public String encode(CharSequence rawPassword) {
   return this.idPrefix + this.idForEncode + this.idSuffix + this.passwordEncoderForEncode.encode(rawPassword);
}

現在你對比一下這個函數跟前面構造函數的名字看看。

構造函數的變量叫 idForEncode , encode函數也叫 idForEncode , 前面的構造函數,我們發(fā)現這個變量其實已經被保存在DelegatingPasswordEncoder類里面了。而且值還是"bcrypt"

而構造函數里面this.passwordEncoderForEncode = idToPasswordEncoder.get(idForEncode)

idToPasswordEncoder就是個Map, k是每種加密對象的id, v是每種加密算法

比如: key = "bcrypt", 那么 value = "BCryptPasswordEncoder"

所以 idToPasswordEncoderencode 函數時, 是BCryptPasswordEncoder

小白: "什么玩意兒, 亂七八糟的, 看不懂"

小黑: "抱歉表達能力不行, 我簡單點說"

小黑: "因為PasswordEncoderFactories.createDelegatingPasswordEncoder()函數使用bcrypt作為默認加密方式, 所以在調用PasswordEncoder.encode時默認也使用bcrypt"

小黑: "還不懂就配合下面的圖片看看"

造成它默認是BCryptPasswordEncoder的原因是什么?

就上面這一行代碼

搞懂這個有什么作用呢?

Spring security默認全部加密方式升級方案全部都是bcrypt,那如果我們要自定義升級到我們需要的加密方式呢?

重寫PasswordEncoderFactories類, 把上面的變量修改成你需要修改的加密類型, 并且往Map中添加加密類型的對象

public static PasswordEncoder createDelegatingPasswordEncoder() {
   String encodingId = "無敵加密";
   Map<String, PasswordEncoder> encoders = new HashMap<>();
   encoders.put(encodingId, new 無敵加密PasswordEncoder());
    // 省略一堆代碼
   return new DelegatingPasswordEncoder(encodingId, encoders);
}

我去跑題了, 回歸正題

第二種方式: 多繼承接口方式

public class UserService implements UserDetailsService, UserDetailsPasswordService {
   @Resource
   private UsersMapper usersMapper;
   /**
    * 升級用戶密碼為當前加密方式
    *
    * @param user        要修改的用戶, 這個用戶必須有 id
    * @param newPassword 新的密碼, 該密碼已經被 passwordEncoder 加密
    * @return
    */
   @Override
   public UserDetails updatePassword(UserDetails user, String newPassword) {
      if (user instanceof Users users) {
         users.setPassword(newPassword);
         usersMapper.updateByPrimaryKeySelective(users);
      }
      return user;
   }
   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      Optional<Users> optionalUsers = Optional.ofNullable(usersMapper.loadUserByUsername(username));
      return optionalUsers.orElseThrow(() -> new UsernameNotFoundException("找不到用戶"));
   }
}

這種方式對應著上面三張圖片的第1張圖片給出的方案

第三種方式: HttpSecurity直接添加

@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
   AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
   authenticationManagerBuilder.authenticationProvider(/* 你的認證七 */)
         .userDetailsService(/* 加載用戶方式 */)
         .passwordEncoder(/* 密碼加密方式 */)
         .userDetailsPasswordManager(/* 第三種更新加密的方式 */);
   return authenticationManagerBuilder.build();
}

這種方式比較麻煩, 只有你需要重寫某個Provider的時候才會用到

一般我們使用第二種方式就行

以上就是Spring Security如何實現升級密碼加密方式詳解的詳細內容,更多關于Spring Security升級密碼加密的資料請關注腳本之家其它相關文章!

相關文章

  • Spring?MVC基于注解的使用之JSON數據處理的方法

    Spring?MVC基于注解的使用之JSON數據處理的方法

    這篇文章主要介紹了Spring?MVC基于注解的使用JSON數據處理,json是一種輕量級的數據交換格式,是一種理想的數據交互語言,它易于閱讀和編寫,同時也易于機器解析和生成,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • SpringBoot整合MP通過Redis實現二級緩存方式

    SpringBoot整合MP通過Redis實現二級緩存方式

    這篇文章主要介紹了SpringBoot整合MP通過Redis實現二級緩存方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • java的各種集合為什么不安全(List、Set、Map)以及代替方案

    java的各種集合為什么不安全(List、Set、Map)以及代替方案

    這篇文章主要介紹了java的各種集合為什么不安全(List、Set、Map)以及代替方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • 在SpringBoot中更改默認端口的方法總結

    在SpringBoot中更改默認端口的方法總結

    在本文中,小編將帶大家學習如何在 Spring Boot 中更改默認端口,默認情況下,嵌入式 Web 服務器使用 8080端口來啟動 Spring 引導應用程序,有幾種方法可以更改該端口,文中介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • java中如何判斷數組中是否包含某個元素的幾種方法

    java中如何判斷數組中是否包含某個元素的幾種方法

    相信大家在操作Java的時候,經常會要檢查一個數組(無序)是否包含一個特定的值,這篇文章主要給大家介紹了關于java中如何判斷數組中是否包含某個元素的幾種方法,需要的朋友可以參考下
    2024-08-08
  • Java如何給變量取合適的命名

    Java如何給變量取合適的命名

    這篇文章主要介紹了Java如何給變量取合適的命名,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • Java基礎知識匯總

    Java基礎知識匯總

    這篇文章對Java編程語言的基礎知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考。
    2017-09-09
  • Java結構性設計模式中的裝飾器模式介紹使用

    Java結構性設計模式中的裝飾器模式介紹使用

    裝飾器模式又名包裝(Wrapper)模式。裝飾器模式以對客戶端透明的方式拓展對象的功能,是繼承關系的一種替代方案,本篇文章以虹貓藍兔生動形象的為你帶來詳細講解
    2022-09-09
  • IDEA的默認快捷鍵設置與Eclipse的常用快捷鍵的設置方法

    IDEA的默認快捷鍵設置與Eclipse的常用快捷鍵的設置方法

    這篇文章主要介紹了IDEA的默認快捷鍵設置與Eclipse的常用快捷鍵的設置方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • Java @GlobalLock注解詳細分析講解

    Java @GlobalLock注解詳細分析講解

    這篇文章主要介紹了Java @GlobalLock注解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-11-11

最新評論