還是回到這張圖:我們想不止使用資料庫查詢的方法去實現認證,而是使用一個統一的認證方法,首先需要修改DaoAuthenticationProvider內實現功能7的方法
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
//詳細參見DaoAuthenticationProvider原始碼,本方法主要是用於判斷憑據、匹配密碼
因此我們需要重寫DaoAuthenticationProvider,將該方法置空,這樣後續使用微信掃碼、簡訊驗證的時候不需要進入這一環節
@Component @Slf4j public class DaoAuthenticationProviderCustom extends DaoAuthenticationProvider { @Autowired public void setUserDetailsService(UserDetailsServiceImpl userDetailsService) { super.setUserDetailsService(userDetailsService);//將自定義的UserDetailsService注入 } @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { } }
接下來我們繼續重構UserDetailsServiceImpl,讓其呼叫不同認證方法實現認證:
建立AuthService介面,透過密碼登入實現類,微信掃碼實現類等實現介面(策略模式),這時一個介面有了多個實現方法,我們該如何使用具體方法?
1.注入ApplicationContext
@Autowired
ApplicationContext applicationContext;
2.透過getBean方法獲取具體bean
AuthService authService = applicationContext.getBean(beanName, AuthService.class);
//authService.xxx()
3.密碼校驗實現類
@Service("passwordAuthServiceImpl") public class PasswordAuthServiceImpl implements AuthService { @Autowired XcUserMapper xcUserMapper; @Autowired PasswordEncoder passwordEncoder; @Autowired CheckCodeClient checkCodeClient; @Override public XcUserExt execute(AuthParamsDto authParamsDto) { if (StringUtils.isEmpty(authParamsDto.getCheckcode())||StringUtils.isEmpty(authParamsDto.getCheckcodekey())) { throw new RuntimeException("驗證碼失效了!再試試吧"); } // feign來校驗驗證碼 Boolean verify = checkCodeClient.verify(authParamsDto.getCheckcodekey(), authParamsDto.getCheckcode()); if(verify==null||!verify){ throw new RuntimeException("驗證碼校驗失敗"); } String username = authParamsDto.getUsername(); XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().eq(XcUser::getUsername, username)); if(Objects.isNull(xcUser)){ throw new RuntimeException("使用者不存在"); } String password = authParamsDto.getPassword(); if(!passwordEncoder.matches(password,xcUser.getPassword())){ throw new RuntimeException("賬號或密碼不正確"); } XcUserExt xcUserExt = new XcUserExt(); BeanUtils.copyProperties(xcUser,xcUserExt); return xcUserExt; } }