1. 程式人生 > >spring-security-oauth2(六) 簡訊驗證碼介面開發

spring-security-oauth2(六) 簡訊驗證碼介面開發

簡訊驗證碼介面開發

  1. 簡訊驗證碼生成介面
  2. 簡訊驗證碼傳送介面
  3. 簡訊生成策略模板模式重構

1.簡訊驗證碼介面開發

1.1簡訊驗證碼生成介面

傳送簡訊驗證碼controller

package com.rui.tiger.auth.core.captcha;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 驗證碼控制器
 *
 * @author CaiRui
 * @date 2018-12-10 12:13
 */
@RestController
@Slf4j
public class CaptchaController {

    public static final String CAPTCHA_SESSION_KEY = "captcha_session_key";
    private static final String FORMAT_NAME = "JPEG";

    @Autowired
    private CaptchaGenerate imageCaptchaGenerate;
    @Autowired
    private CaptchaGenerate smsCaptchaGenerate;
    @Autowired
    private SmsCaptchaSend smsCaptchaSend;

    //spring session 工具類
    private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();

    /**
     * 獲取圖片驗證碼
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping("/captcha/image")
    public void createKaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1.介面生成驗證碼
        ImageCaptchaVo imageCaptcha = (ImageCaptchaVo) imageCaptchaGenerate.generate();
        //2.儲存到session中
        sessionStrategy.setAttribute(new ServletWebRequest(request), CAPTCHA_SESSION_KEY, imageCaptcha);
        //3.寫到響應流中
        response.setHeader("Cache-Control", "no-store, no-cache");// 沒有快取
        response.setContentType("image/jpeg");
        ImageIO.write(imageCaptcha.getImage(), FORMAT_NAME, response.getOutputStream());
    }


    /**
     * 獲取圖片驗證碼
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping("/captcha/sms")
    public void createSms(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletRequestBindingException {
        log.info("獲取簡訊驗證碼");
        //1.獲取簡訊驗證碼
        CaptchaVo captchaVo = smsCaptchaGenerate.generate();
        //2.儲存到session中
        sessionStrategy.setAttribute(new ServletWebRequest(request), CAPTCHA_SESSION_KEY + "sms", captchaVo);
        //3.傳送
        String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
        smsCaptchaSend.sendSms(mobile, captchaVo.getCode());
    }


}

由於簡訊驗證碼和圖片驗證碼基本結構都差不多,只是沒有圖形,故對實體進行調整

package com.rui.tiger.auth.core.captcha;

import lombok.Data;

import java.awt.image.BufferedImage;
import java.time.LocalDateTime;

/**
 * 驗證碼
 *
 * @author CaiRui
 * @Date 2018/12/15 9:11
 */
@Data
public class CaptchaVo {
    /**
     * 驗證碼
     */
    private String code;
    /**
     * 失效時間 這個通常放在快取中或維護在資料庫中
     */
    private LocalDateTime expireTime;

    public CaptchaVo(String code, int expireAfterSeconds) {
        this.code = code;
        //多少秒後
        this.expireTime = LocalDateTime.now().plusSeconds(expireAfterSeconds);
    }

    public CaptchaVo(String code, LocalDateTime expireTime) {
        this.code = code;
        this.expireTime = expireTime;
    }
    /**
     * 是否失效
     *
     * @return
     */
    public boolean isExpried() {
        return LocalDateTime.now().isAfter(expireTime);
    }
}
package com.rui.tiger.auth.core.captcha;

import lombok.Data;

import java.awt.image.BufferedImage;
import java.time.LocalDateTime;

/**
 * 圖片驗證碼資訊物件
 *
 * @author CaiRui
 * @Date 2018/12/9 18:03
 */
@Data
public class ImageCaptchaVo extends CaptchaVo {
    /**
     * 圖片驗證碼
     */
    private BufferedImage image;

    public ImageCaptchaVo(BufferedImage image, String code, int expireAfterSeconds) {
        super(code, expireAfterSeconds);
        this.image = image;
    }

    public ImageCaptchaVo(BufferedImage image, String code, LocalDateTime expireTime) {
        super(code, expireTime);
        this.image = image;
    }
}

相關配置類調整修改

package com.rui.tiger.auth.core.properties;

/**
 * 簡訊驗證碼配置類
 * @author CaiRui
 * @Date 2018/12/15 9:30
 */
public class SmsCaptchaProperties {
    /**
     * 長度
     */
    private int length=6;
    /**
     * 過期秒數 預設3分鐘
     */
    private int expireSeconds=180;

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getExpireSeconds() {
        return expireSeconds;
    }

    public void setExpireSeconds(int expireSeconds) {
        this.expireSeconds = expireSeconds;
    }

}
package com.rui.tiger.auth.core.properties;

/**
 * 驗證碼配置類
 * @author CaiRui
 * @Date 2018/12/15 9:43
 */
public class CaptchaProperties {
    /**
     *圖片驗證碼配置
     */
    private ImageCaptchaProperties image=new ImageCaptchaProperties();
    /**
     * 簡訊驗證碼配置
     */
    private SmsCaptchaProperties sms=new SmsCaptchaProperties();

    public ImageCaptchaProperties getImage() {
        return image;
    }

    public void setImage(ImageCaptchaProperties image) {
        this.image = image;
    }

    public SmsCaptchaProperties getSms() {
        return sms;
    }

    public void setSms(SmsCaptchaProperties sms) {
        this.sms = sms;
    }
}
package com.rui.tiger.auth.core.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 許可權配置檔案父類(注意這裡不用lombok 會讀取不到)
 * 這裡會有很多許可權配置子模組
 *
 * @author CaiRui
 * @date 2018-12-6 8:41
 */

@ConfigurationProperties(value = "tiger.auth", ignoreInvalidFields = true)
public class SecurityProperties {
    /**
     * 瀏覽器配置類
     */
    private BrowserProperties browser = new BrowserProperties();
    /**
     * 驗證碼配置類
     */
    private CaptchaProperties captcha = new CaptchaProperties();

    public BrowserProperties getBrowser() {
        return browser;
    }

    public void setBrowser(BrowserProperties browser) {
        this.browser = browser;
    }

    public CaptchaProperties getCaptcha() {
        return captcha;
    }

    public void setCaptcha(CaptchaProperties captcha) {
        this.captcha = captcha;
    }
}

簡訊驗證碼生成介面及實現類

package com.rui.tiger.auth.core.captcha;

/**
 * 驗證碼生成介面
 *
 * @author CaiRui
 * @date 2018-12-10 12:03
 */
public interface CaptchaGenerate {
	/**
	 * 生成驗證碼
	 *
	 * @return
	 */
	CaptchaVo generate();
}
package com.rui.tiger.auth.core.captcha;

import com.rui.tiger.auth.core.properties.SecurityProperties;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 簡訊驗證碼生成器
 *
 * @author CaiRui
 * @Date 2018/12/15 9:10
 */
@Component("smsCaptchaGenerate")
public class SmsCaptchaGenerate implements CaptchaGenerate {

    @Autowired
    private SecurityProperties securityProperties;
    /**
     * 生成簡訊驗證碼
     *
     * @return
     */
    @Override
    public CaptchaVo generate() {
        String code = RandomStringUtils.randomNumeric(securityProperties.getCaptcha().getSms().getLength());
        return new CaptchaVo(code, securityProperties.getCaptcha().getSms().getExpireSeconds());
    }
}

 

1.2簡訊登陸碼傳送介面

簡訊驗證碼傳送介面及其實現類

package com.rui.tiger.auth.core.captcha;

/**
 * 簡訊驗證碼傳送介面
 * @author CaiRui
 * @Date 2018/12/15 10:03
 */
public interface SmsCaptchaSend {

    /**
     * 傳送簡訊驗證碼
     * @param mobile
     * @param code
     * @return
     */
    boolean sendSms(String mobile,String code);

}
package com.rui.tiger.auth.core.captcha;

import lombok.extern.slf4j.Slf4j;

/**
 * @author CaiRui
 * @Date 2018/12/15 10:05
 */
@Slf4j
public class DefaultSmsCaptchaSender implements SmsCaptchaSend {

    //實際生產環境中,呼叫渠道供應商傳送簡訊
    @Override
    public boolean sendSms(String mobile, String code) {
        log.info("模擬向手機{}傳送簡訊驗證碼{}",mobile,code);
        log.info("簡訊渠道傳送中...傳送成功");
        return true;
    }

}

驗證碼配置類

package com.rui.tiger.auth.core.config;

import com.google.code.kaptcha.Producer;
import com.rui.tiger.auth.core.captcha.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 驗證碼Bean生成配置類
 *
 * @author CaiRui
 * @date 2018-12-12 8:41
 */
@Configuration
public class CaptchaBeanConfig {

	//圖片驗證碼生成
	@Bean
	// spring 容器中如果存在imageCaptchaGenerate的bean就不會再初始化該bean了
	//可參見:https://www.cnblogs.com/yixianyixian/p/7346894.html 這篇博文
	@ConditionalOnMissingBean(name = "imageCaptchaGenerate")
	public CaptchaGenerate imageCaptchaGenerate() {
		ImageCaptchaGenerate imageCaptchaGenerate = new ImageCaptchaGenerate();
		return imageCaptchaGenerate;
	}
	//簡訊驗證碼生成
	@Bean
	@ConditionalOnMissingBean(name = "smsCaptchaGenerate")
	public CaptchaGenerate smsCaptchaGenerate() {
		SmsCaptchaGenerate smsCaptchaGenerate = new SmsCaptchaGenerate();
		return smsCaptchaGenerate;
	}

	@Bean
	@ConditionalOnMissingBean(DefaultSmsCaptchaSender.class)
	public SmsCaptchaSend defaultSmsCaptchaSender() {
		DefaultSmsCaptchaSender defaultSmsCaptchaSender=new DefaultSmsCaptchaSender();
		return defaultSmsCaptchaSender;
	}

}

在許可權路徑中放行 .antMatchers(securityProperties.getBrowser().getLoginPage(), "/authentication/require", "/captcha/*")

package com.rui.tiger.auth.browser.config;

import com.rui.tiger.auth.core.authentication.TigerAuthenticationFailureHandler;
import com.rui.tiger.auth.core.authentication.TigerAuthenticationSuccessHandler;
import com.rui.tiger.auth.core.captcha.CaptchaFilter;
import com.rui.tiger.auth.core.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * 瀏覽器security配置類
 *
 * @author CaiRui
 * @date 2018-12-4 8:41
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private SecurityProperties securityProperties;
	@Autowired
	private TigerAuthenticationFailureHandler tigerAuthenticationFailureHandler;
	@Autowired
	private TigerAuthenticationSuccessHandler tigerAuthenticationSuccessHandler;
	@Autowired
	private DataSource dataSource;
	@Autowired
	private UserDetailsService userDetailsService;

	/**
	 * 密碼加密解密
	 *
	 * @return
	 */
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	/**
	 * 記住我持久化資料來源
	 * JdbcTokenRepositoryImpl  CREATE_TABLE_SQL 建表語句可以先在資料庫中執行
	 *
	 * @return
	 */
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
		jdbcTokenRepository.setDataSource(dataSource);
		//第一次會執行CREATE_TABLE_SQL建表語句 後續會報錯 可以關掉
		//jdbcTokenRepository.setCreateTableOnStartup(true);
		return jdbcTokenRepository;
	}


	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//加入圖片驗證碼過濾器
		CaptchaFilter captchaFilter = new CaptchaFilter();
		captchaFilter.setFailureHandler(tigerAuthenticationFailureHandler);
		captchaFilter.setSecurityProperties(securityProperties);
		captchaFilter.afterPropertiesSet();

		//圖片驗證碼放在認證之前
		http.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
				.formLogin()
				.loginPage("/authentication/require")//自定義登入請求
				.loginProcessingUrl("/authentication/form")//自定義登入表單請求
				.successHandler(tigerAuthenticationSuccessHandler)
				.failureHandler(tigerAuthenticationFailureHandler)
				.and()
				//記住我相關配置
				.rememberMe()
				.tokenRepository(persistentTokenRepository())
				.tokenValiditySeconds(securityProperties.getBrowser().getRemberMeSeconds())
				.userDetailsService(userDetailsService)
				.and()
				.authorizeRequests()
				.antMatchers(securityProperties.getBrowser().getLoginPage(),
						"/authentication/require", "/captcha/*")//此路徑放行 否則會陷入死迴圈
				.permitAll()
				.anyRequest()
				.authenticated()
				.and()
				.csrf().disable()//跨域關閉
		;
	}

}

postman測試下

看控制檯日誌,可以看見我們的簡訊傳送介面可以用

1.3 驗證碼生成策略模板方式重構

經過分析圖片驗證碼和手機驗證碼的建立流程基本都是一樣,主要經過三步。

  1. 生成驗證碼
  2. 儲存到session中
  3. 傳送(圖片響應流寫回,簡訊呼叫渠道直接傳送)

下面結合UML圖和程式碼看看是怎麼實現的吧。

CaptchaController呼叫CaptchaCreateService,CaptchaCreateService策略呼叫CaptchaProcessor

CaptchaController 經過調整後如下,將原來的分別生成圖片和簡訊的合併調整

package com.rui.tiger.auth.core.captcha;

import com.rui.tiger.auth.core.captcha.sms.SmsCaptchaSend;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 驗證碼控制器
 *
 * @author CaiRui
 * @date 2018-12-10 12:13
 */
@RestController
@Slf4j
public class CaptchaController {
    @Autowired
    private CaptchaCreateService captchaCreateService;
    /**
     * 獲取驗證碼
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping("/captcha/{type}")
    public void createCaptcha(HttpServletRequest request, HttpServletResponse response, @PathVariable String type) throws Exception {
        log.info("獲取驗證碼開始");
        captchaCreateService.createCaptcha(new ServletWebRequest(request, response), type);
        log.info("獲取驗證碼結束");
    }
}

驗證碼生成介面

package com.rui.tiger.auth.core.captcha;

import org.springframework.web.context.request.ServletWebRequest;

/**
 * @author CaiRui
 * @Date 2018/12/15 21:27
 */
public interface CaptchaCreateService {
    /**
     *  生成驗證碼
     * @param request
     * @param type
     */
    void createCaptcha(ServletWebRequest request, String type);
}
package com.rui.tiger.auth.core.captcha;

import com.rui.tiger.auth.core.support.strategy.StrategyContainerImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.ServletWebRequest;

/**
 * @author CaiRui
 * @Date 2018/12/15 21:27
 */
@Service
@Slf4j
public class CaptchaCreateServiceImpl implements CaptchaCreateService {
    /**
     * 生成驗證碼
     *
     * @param request
     * @param type
     */
    @Override
    public void createCaptcha(ServletWebRequest request, String type) {
        CaptchaTypeEnum captchaType=CaptchaTypeEnum.forCode(type);
        if   (type==null){
            throw new  CaptchaException("驗證碼型別不支援");
        }
        try {
            StrategyContainerImpl.getStrategy(CaptchaProcessor.class,captchaType)
                    .create(request);
        } catch (Exception e) {
            log.info("");
        }
    }
}

驗證碼型別列舉類

package com.rui.tiger.auth.core.captcha;

import java.util.HashMap;
import java.util.Map;

/**
 * 驗證碼型別列舉類
 * @author CaiRui
 * @Date 2018/12/15 17:58
 */
public enum CaptchaTypeEnum {

    SMS("sms","簡訊"),
    IMAGE("image","圖形驗證碼");

    CaptchaTypeEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    private static Map<String,CaptchaTypeEnum> codeLookup = new HashMap<String,CaptchaTypeEnum>();
    private String code;
    private String desc;

    static {
        for (CaptchaTypeEnum type : CaptchaTypeEnum.values()) {
            codeLookup.put(type.code, type);
        }
    }

    /**
     * 根據型別獲取列舉類
     * @param code
     * @return
     */
    public static CaptchaTypeEnum forCode(String code)  {
        return codeLookup.get(code);
    }

    public String getCode() {
        return code;
    }

}

驗證碼生成策略介面,

package com.rui.tiger.auth.core.captcha;

import com.rui.tiger.auth.core.support.strategy.IStrategy;
import org.springframework.web.context.request.ServletWebRequest;

/**
 * 驗證碼處理器介面
 * @author CaiRui
 * @Date 2018/12/15 17:53
 */
public interface CaptchaProcessor extends IStrategy<CaptchaTypeEnum> {
    /**
     * 驗證碼
     */
    String CAPTCHA_SESSION_KEY="captcha_session_key_";
    /**
     * 建立驗證碼
     * @param request 封裝請求和響應
     * @throws Exception
     */
    void create(ServletWebRequest request) throws  Exception;
}

抽象實現父類

package com.rui.tiger.auth.core.captcha;

import org.apache.commons.lang.StringUtils;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.context.request.ServletWebRequest;

import java.io.IOException;

/**
 * 驗證碼處理器抽象父類
 * @author CaiRui
 * @Date 2018/12/15 18:21
 */
public abstract class AbstractCaptchaProcessor<C extends CaptchaVo> implements CaptchaProcessor {

    private SessionStrategy sessionStrategy=new HttpSessionSessionStrategy();
    /**
     * 建立驗證碼
     *
     * @param request 封裝請求和響應
     * @throws Exception
     */
    @Override
    public void create(ServletWebRequest request) throws Exception {
        //生成
        C captcha=generateCaptcha(request);
        //儲存
        save(request,captcha);
        //傳送
        send(request,captcha);
    }

    protected abstract C generateCaptcha(ServletWebRequest request);

    protected abstract void send(ServletWebRequest request, C captcha) throws IOException, ServletRequestBindingException;

    private void save(ServletWebRequest request, C captcha) {
        sessionStrategy.setAttribute(request, CAPTCHA_SESSION_KEY+getCaptchaTypeFromUrl(request), captcha);
    }

    /**
     * 根據請求的url獲取校驗碼的型別
     * @param request
     * @return
     */
    private String getCaptchaTypeFromUrl(ServletWebRequest request) {
        return StringUtils.substringAfter(request.getRequest().getRequestURI(), "/captcha/");
    }


}

圖片驗證碼生成實現

package com.rui.tiger.auth.core.captcha.image;

import com.rui.tiger.auth.core.captcha.AbstractCaptchaProcessor;
import com.rui.tiger.auth.core.captcha.CaptchaGenerate;
import com.rui.tiger.auth.core.captcha.CaptchaTypeEnum;
import com.rui.tiger.auth.core.captcha.ImageCaptchaVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.ServletWebRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author CaiRui
 * @Date 2018/12/15 18:31
 */
@Service
@Slf4j
public class ImageCaptchaProcessor extends AbstractCaptchaProcessor<ImageCaptchaVo> {
    private static final String FORMAT_NAME = "JPEG";

    @Autowired
    private CaptchaGenerate imageCaptchaGenerate;

    /**
     * 獲得策略條件
     *
     * @return 用來註冊的策略處理條件
     */
    @Override
    public CaptchaTypeEnum getCondition() {
        return CaptchaTypeEnum.IMAGE;
    }

    @Override
    protected ImageCaptchaVo generateCaptcha(ServletWebRequest request) {
        return (ImageCaptchaVo) imageCaptchaGenerate.generate();
    }

    @Override
    protected void send(ServletWebRequest request, ImageCaptchaVo captcha) throws IOException {
        HttpServletResponse response=request.getResponse();
        response.setHeader("Cache-Control", "no-store, no-cache");// 沒有快取
        response.setContentType("image/jpeg");
        ImageIO.write(captcha.getImage(), FORMAT_NAME, response.getOutputStream());

    }
}

簡訊驗證碼生成實現

package com.rui.tiger.auth.core.captcha.sms;

import com.rui.tiger.auth.core.captcha.AbstractCaptchaProcessor;
import com.rui.tiger.auth.core.captcha.CaptchaGenerate;
import com.rui.tiger.auth.core.captcha.CaptchaTypeEnum;
import com.rui.tiger.auth.core.captcha.CaptchaVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

/**
 * @author CaiRui
 * @Date 2018/12/15 18:29
 */
@Service
@Slf4j
public class SmsCaptchaProcessor extends AbstractCaptchaProcessor<CaptchaVo> {

    @Autowired
    private CaptchaGenerate smsCaptchaGenerate;
    @Autowired
    private SmsCaptchaSend captchaSend;

    /**
     * 獲得策略條件
     *
     * @return 用來註冊的策略處理條件
     */
    @Override
    public CaptchaTypeEnum getCondition() {
        return CaptchaTypeEnum.SMS;
    }

    @Override
    protected CaptchaVo generateCaptcha(ServletWebRequest request) {
        return smsCaptchaGenerate.generate();
    }

    @Override
    protected void send(ServletWebRequest request, CaptchaVo captcha) throws ServletRequestBindingException {
        String mobile= ServletRequestUtils.getRequiredStringParameter(request.getRequest(),"mobile");
        captchaSend.sendSms(mobile, captcha.getCode());
    }
}

ok  重構完成 下面我們自定義簡訊登陸開發

個人碼雲地址:https://gitee.com/krui/tiger-auth