基於SpringSecurity google 二次驗證
阿新 • • 發佈:2021-12-17
主要就是 增加安全性,類似於 簡訊二次驗證一樣,不過Google 二次驗證 提供的是開源一套演算法,節約成本,很多網站為了真加安全性,都開啟了二次驗證 。
java 具體思路
- 網站或者服務端 開啟二次驗證 ,引入開源工具包
編寫對應的工具類,生成二維碼連結,使用者掃描繫結 祕鑰key
自定義 AuthenticationProvider,UsernamePasswordAuthenticationToken 在校驗完使用者密碼後再 處理 google 校驗邏輯
程式碼
- 修改配置SpringSecurity
httpSecurity.authenticationProvider(new CustomerAuthenticationProvider(userDetailsService,bCryptPasswordEncoder()));
-
自定義 CustomerAuthenticationProvider,CustomerUsernamePasswordAuthenticationToken 直接繼承重寫父類方法就行
public class CustomerAuthenticationProvider extends DaoAuthenticationProvider { public CustomerAuthenticationProvider(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) { super(); setUserDetailsService(userDetailsService); setPasswordEncoder(bCryptPasswordEncoder); } protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (authentication.getCredentials() == null) { this.logger.debug("Failed to authenticate since no credentials provided"); throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } else { String presentedPassword = authentication.getCredentials().toString(); if (!getPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) { this.logger.debug("Failed to authenticate since password does not match stored value"); throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } googleAuthenticator((LoginUser) userDetails, (CustomerUsernamePasswordAuthenticationToken) authentication); } } /** * Google 二次驗證 * @param userDetails * @param authentication */ private void googleAuthenticator(LoginUser userDetails, CustomerUsernamePasswordAuthenticationToken authentication) { // Google 二次驗證 LoginUser loginUser = userDetails; SysUser user = loginUser.getUser(); String googleAuthSecret = user.getGoogleAuthSecret(); if(StringUtils.isBlank(googleAuthSecret)){ throw new ServiceException(GOOGLE_AUTHENTICATOR_401001.getMsg(),GOOGLE_AUTHENTICATOR_401001.getCode()); } CustomerUsernamePasswordAuthenticationToken customerToken = authentication; String code = customerToken.getCode(); boolean valid = GoogleAuthenticatorUtils.valid(googleAuthSecret, Integer.valueOf(code).intValue()); if(!valid){ throw new ServiceException("Google Authenticator 驗證碼錯誤"); } } } public class CustomerUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { /** * Google 二次驗證 生成 code */ private String code; public CustomerUsernamePasswordAuthenticationToken(Object principal, Object credentials) { super(principal, credentials); } public CustomerUsernamePasswordAuthenticationToken(Object principal, Object credentials,String code) { super(principal, credentials); this.code = code; } public CustomerUsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) { super(principal, credentials, authorities); } public String getCode() { return code; } public void setCode(String code) { this.code = code; } } // 呼叫自定義 CustomerUsernamePasswordAuthenticationToken authentication = authenticationManager .authenticate(new CustomerUsernamePasswordAuthenticationToken(username, password,code));