springsecurity透過策略模式設定統一認證介面

天启A發表於2024-07-28

還是回到這張圖:我們想不止使用資料庫查詢的方法去實現認證,而是使用一個統一的認證方法,首先需要修改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;
    }
}

相關文章