Springboot2的Security框架用的是5.0的,較之4.0的密碼加密方式有了很大的改變.spring security 5中主推的加密方式為BCrypt,由於這種加密方式效率很低,屬於慢加密,但是加密強度很高,現有的機器性能難以暴力破解,但是隨着科技的進步,機器性能增強,破解這種加密方式也會成為可能,但是加密方式也會不斷更新.
廢話說到這里,由於性能要求,對該加密登錄的壓測,只能達到50-80qps,這無疑對高並發登錄是不能接受的,所以我們需要改掉這種加密方式,我們選擇了MD5的加密.修改之前的安全配置如下.
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 全局用戶信息
*
* @param auth
* 認證管理
* @throws Exception
* 用戶認證異常信息
*/
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
/**
* 認證管理
*
* @return 認證管理對象
* @throws Exception
* 認證異常信息
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* http安全配置
*
* @param http
* http安全對象
* @throws Exception
* http安全異常信息
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(PermitAllUrl.permitAllUrl()).permitAll().anyRequest().authenticated().and()
.httpBasic().and().csrf().disable();
}
}
修改后,我們只使用MD5進行加密
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public UserDetailsService userDetailsService;
// @Bean
// public BCryptPasswordEncoder bCryptPasswordEncoder() {
// return new BCryptPasswordEncoder();
// }
@Bean
PasswordEncoder passwordEncoder(){
String idForEncode = "MD5";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
PasswordEncoder delegatingPasswordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);
return delegatingPasswordEncoder;
// return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
/**
* 全局用戶信息
*
* @param auth
* 認證管理
* @throws Exception
* 用戶認證異常信息
*/
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
/**
* 認證管理
*
* @return 認證管理對象
* @throws Exception
* 認證異常信息
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* http安全配置
*
* @param http
* http安全對象
* @throws Exception
* http安全異常信息
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(PermitAllUrl.permitAllUrl()).permitAll().anyRequest().authenticated().and()
.httpBasic().and().csrf().disable();
}
}
這里需要注意的是,由於只使用了MD5進行加密,在訪問的時候,假設我們使用的是superadmin用戶名,密碼123456
http://192.168.5.182:36178/oauth/token?grant_type=password&client_id=system&client_secret=system&scope=app&username=superadmin&password=123456
這個client_id=system&client_secret=system在數據庫中是有對應的,之前的對應是用BCrypt加密的,所以在oauth_client_details表中,是這樣的

這里面的client_secret的值其實是system字符串的BCrypt加密結果,我們需要改成如下所示

這個值同樣也是system,不過是由MD5加密的結果,主要需要加前綴{MD5}.這樣在app_user表中,信息如下
![]()
密碼是由123456的MD5加密結果.這樣在訪問中,我們就可以獲取訪問的結果access_token
{"access_token":"65411be1-b7be-46e5-8d72-c0624da33ed7","token_type":"bearer","refresh_token":"43eb498f-d431-4c96-a5b5-3bc007c9c189","expires_in":25690,"scope":"app"}
但值得注意的是,有時候這樣修改后未必能得到我們所需要的結果,那是因為在redis中的緩存問題,由於前一次在BCrypt的加密下已經有了緩存,所以會報錯,我們需要手工清除一下Redis中的緩存,這樣就會重新建立MD5加密后的緩存,就不會再出現問題了.經過壓測,結果已經達到了2000左右的qps,已經大大高於50-80了.
