主要就是 增加安全性火的,類似于 短信二次驗(yàn)證一樣壶愤,不過Google 二次驗(yàn)證 提供的是開源一套算法,節(jié)約成本馏鹤,很多網(wǎng)站為了真加安全性,都開啟了二次驗(yàn)證 娇哆。
java 具體思路
- 網(wǎng)站或者服務(wù)端 開啟二次驗(yàn)證 ,引入開源工具包
編寫對應(yīng)的工具類湃累,生成二維碼鏈接勃救,用戶掃描綁定 秘鑰key
自定義 AuthenticationProvider,UsernamePasswordAuthenticationToken 在校驗(yàn)完用戶密碼后再 處理 google 校驗(yàn)邏輯
代碼
- 修改配置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 二次驗(yàn)證 * @param userDetails * @param authentication */ private void googleAuthenticator(LoginUser userDetails, CustomerUsernamePasswordAuthenticationToken authentication) { // Google 二次驗(yàn)證 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 驗(yàn)證碼錯(cuò)誤"); } } } public class CustomerUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { /** * Google 二次驗(yàn)證 生成 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; } } // 調(diào)用自定義 CustomerUsernamePasswordAuthenticationToken authentication = authenticationManager .authenticate(new CustomerUsernamePasswordAuthenticationToken(username, password,code));