【Spring Security】增加RSA密文傳輸登錄

背景

由於原來登錄表單和oauth/token使用時,是走明文傳輸的。爲了保證傳輸中不容易被竊取,採用RSA加密明文密碼後再進行傳輸,後臺仍然是BCrypt的方式存入數據庫。但通過查閱資料,有些寫法是通過繼承PasswordEncoder的方式實現,但在5.x版本中,自定義的加密器會缺少id,所以需要換個方式實現。

版本

  •  Spring Security:5.x

預定方案

  1. 或許可以註冊增加一個類似UsernamePasswordAuthenticationFilter的filter,加入到filter鏈(沒嘗試過,本文不開展)
  2. 增加AuthenticationProvider身份認證模式實現,本文由此開展

步驟

定義一個RSA密文身份認證類

核心就是從認證信息authentication中拿到密文,調用RSA工具解密,再將解密後的密碼與數據庫密碼進行BCrypt對比,正確則構造token信息,錯誤則拋出異常。

@Component
public class CustomUserAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserDetailsService userDetailsService;
     
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    /**
     * 認證處理,返回一個Authentication的實現類則代表認證成功,拋出CredentialsExpiredException則失敗
     * @param authentication 認證信息
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        //獲取用戶信息
        UserDetails user = userDetailsService.loadUserByUsername(username);
        
        //比較前端傳入的密碼和數據庫中加密的密碼是否相等
 	String plainText = RSAUtil.decrypt(password);
 	
        if (!passwordEncoder.matches(plainText, user.getPassword())) {
            throw new CredentialsExpiredException("密碼不一致");
        }
        
        //獲取用戶權限信息
        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        return new UsernamePasswordAuthenticationToken(user, password, authorities);
     }
     /**
      * 如果該AuthenticationProvider支持傳入的Authentication對象,則返回true
      */
     @Override
     public boolean supports(Class<?> clazz) {
         return clazz.equals(UsernamePasswordAuthenticationToken.class);
     }

}

將認證類配置到Security配置裏

在Security配置類中,構造實例並裝載到Bean中,並設置爲AuthenticationManagerBuilder的一個參數。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebServerSecurityConfig extends WebSecurityConfigurerAdapter {
    
   // 不相關代碼略去

    /**
     * 注入自定義的userDetailsService實現,獲取用戶信息,設置密碼加密方式
     *
     * @param authenticationManagerBuilder
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
	authenticationManagerBuilder
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder())
                .and()
                .authenticationProvider(userAuthenticationProvider())
                .eraseCredentials(false); // 不清除密碼,後續需要手動清除
    }

    /**
     * BCrypt加密器
     * @return 加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    /**
     * 自定義認證操作
     * @return 認證操作
     */
    @Bean
    public AuthenticationProvider userAuthenticationProvider() {
	return new CustomUserAuthenticationProvider();
    }

}

參考資料

https://blog.csdn.net/yaomingyang/article/details/98785488

 

 

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