ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

aliyun阿里云发送短信验证码和校验

2021-10-08 15:58:55  阅读:208  来源: 互联网

标签:和校验 code return String tokenId 验证码 aliyun type public


第一步。前端调用发送短信验证码的接口

  @Autowired
    private ResetPasswordService resetPasswordService;

    @GetMapping("/validate-code")
    public Result validateCode(@RequestParam String phone) {
        return resetPasswordService.validateCode(phone);
    }

第二步,生成验证码并发送(自主生成验证码),反馈给前端

	@Autowired
    private IIdentifyingCodeService identifyingCodeService;
    
	public static final String USER_REGISTER_PASSWORD = "register_password";
	//要发送的短信内容
    private String templateOfRegisterStoreSms = "【***-**】%s(****验证码)。工作人员不会向您索要,请勿向任何人泄露,以免造成账户或资金损失。";
    //验证码的生成范围
    private int startInclusive = 1000;
    private int endInclusive = 9999;
    //验证码有效期
    private int expire = 60 * 1000;
    
	@Override
    public String validateCode(String phone) {
		//生成验证码
        int code = RandomUtils.nextInt(startInclusive, endInclusive);
        
        String tokenId= identifyingCodeService.sendCode(phone, USER_REGISTER_PASSWORD, templateOfRegisterStoreSms,String.valueOf(code), expire);
        return tokenId;
    }

第三步,发送验证码的service和impl


/**
 * identifying code service
 * @author author 
 * @date 2020年2月14日
 */
public interface IIdentifyingCodeService {

    /**
     * 发送认证码
     * @param target 目标,一般为手机号
     * @param type 类型,该类型由具体的使用者自定义即可,只要确保在本方法使用中的type一致即可,该字段作为tokenId的一部分
     * @param template 消息模板,的定义,默认使用 %s 来格式化字符串,即模板中包含的 %s 将被 参数 code 替换
     * @param code 认证码,请自主生成
     * @param expire 超时时间,该认证码失效的时间,单位为秒
     * @return tokenId 认证码与本tokenId一一对应
     */
    String sendCode(String target, String type, String template, String code, int expire);

    /**
     * 获取tokenId对应的code
     * @param type 参考上述定义
     * @param tokenId
     * @return code
     */
    String getCode(String type, String tokenId);

    /**
     * 清空tokenId对应的code
     * @param type 参考上述定义
     * @param tokenId }方法返回的tokenId
     * @return code
     */
    void clean(String type, String tokenId);
}


/**
 * identifying code service impl
 * @author author 
 * @date 2020年2月14日
 */
@Service
@Slf4j
public class IIdentifyingCodeServiceImpl implements IIdentifyingCodeService {

    public static final String PREFIX_SMS = "SMS";
    public static final String PREFIX_IDENTIFYING = "IDENTIFYING";
    public static final String IDENTIFYING_TYPE_OF_POLICY = "policy";

    private  String separator = ":";
    private  int keyLength = 10;
    private  int policyTime = 60 * 1000;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public String sendCode(String target, String type, String template, String code, int expire) {
        Result result = timePolicy(target, policyTime);
        if(result.getCode().equals(ResultEnum.OPRATOR_FAIL.getCode())){
            return result;
        }
        //阿里发送短信验证码
        AliSMSClient.sendSMS(target,code);
        String tokenId = generatorTokenId();
        redisUtils.setValue(generatorKey(type, tokenId), code, expire);
        return tokenId;
    }

    protected String generatorKey(String type, String tokenId) {
        String key = new StringBuffer()
                .append(PREFIX_SMS)
                .append(separator)
                .append(PREFIX_IDENTIFYING)
                .append(separator)
                .append(type)
                .append(separator)
                .append(tokenId).toString();
        return key;
    }

    protected String generatorTokenId() {
        return RandomStringUtils.randomAlphabetic(keyLength);
    }

    protected Result timePolicy(String target, int ttl) {
        Object  oTarget= redisUtils.getValue(generatorKey(IDENTIFYING_TYPE_OF_POLICY, target));
        if (Objects.nonNull(oTarget)) {
            log.debug("identifying code time policy: target [{}] is failed. ttl=[{}]", target, ttl);
            return RespUtil.error(ResultEnum.OPRATOR_FAIL.getCode(),ttl / 1000 + "秒内不能再次发送短信");
        } else {
            redisUtils.setValue(generatorKey(IDENTIFYING_TYPE_OF_POLICY, target), target, ttl);
            return  RespUtil.success(ResultEnum.OPRATOR_SUCCESS.getCode());
        }
    }

    @Override
    public String getCode(String type, String tokenId) {
        Object obj = redisUtils.getValue(generatorKey(type, tokenId));
        if(Objects.isNull(obj)){
            return "";
        }
        return (String)obj;
    }

    @Override
    public void clean(String type, String tokenId) {
        redisUtils.setValue(generatorKey(type, tokenId), null);
    }
}

第四步,ali发送短信的接口

/**
 * 静态常量类
 * @author author 
 *
 */
public class Constants {

	/** 阿里  短信发送访问域名 */
	public static final String endpoint = "dysmsapi.aliyuncs.com";
	/** 阿里  AccessKey ID */
	public static final String accessKeyId = "accessKeyId ";
	/** 阿里  AccessKey Secret */
	public static final String accessKeySecret = "accessKeySecret ";
	/** 阿里  signName */
	public static final String signName = "signName";
	/** 阿里  templateCode */
	public static final String templateCode = "templateCode ";

}
/**
 * 
 * @author author 
 *
 */
public class AliSMSClient {

	private static Logger logger = LoggerFactory.getLogger(AliSMSClient.class);

	private AliSMSClient(){
		
	}

	public static void main(String[] args) {
		sendSMS("18700000000", "3456");
	}

	/**
	 * 使用AK&SK初始化账号Client
	 * @return Client
	 * @throws Exception
	 */
	public static Client createClient() throws Exception {
		Config config = new Config()
				// 您的AccessKey ID
				.setAccessKeyId(Constants.accessKeyId)
				// 您的AccessKey Secret
				.setAccessKeySecret(Constants.accessKeySecret)
				// 访问的域名
				.setEndpoint(Constants.endpoint);

		return new Client(config);
	}

	/**
	 * 发送短信
	 * @param phone
	 * @param SignName  短信签名名称
	 * @param TemplateCode 短信模板ID
	 * @return
	 * @throws Exception
	 */
	public static String sendSMS(String phone,String templateParam) {

		if(StringUtils.isBlank(phone)) {
			throw new IllegalArgumentException("手机号不能为空");
		}

		Client client = null;
		String ret = "";
		try {
			client = createClient();
			SendSmsRequest sendSmsRequest = new SendSmsRequest()
					.setPhoneNumbers(phone)
					.setSignName(Constants.signName)
					.setTemplateCode(Constants.templateCode)
					.setTemplateParam("{'code':'" + templateParam + "'}");
			SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
			if (null != sendSmsResponse && !"".equals(sendSmsResponse)) {
				ret = parseResponse(sendSmsResponse);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new CustomException("发送短信失败!");
		}
		return ret;
	}

	/**
	 * 解析下发response
	 * @param sendSmsResponse
	 * @return
	 */
	public static String parseResponse(SendSmsResponse sendSmsResponse) {

		//"Message":"OK", 状态码的描述。
		//"RequestId":"2184201F-BFB3-446B-B1F2-C746B7BF0657", 请求ID。
		//"BizId":"197703245997295588^0", 发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。
		//"Code":"OK" 请求状态码,返回OK代表请求成功。

		SendSmsResponseBody body = sendSmsResponse.getBody();
		if("OK".equals(body.getCode())){
			return "0";
		}else {
			return "-1";
		}
	}
}

下面是验证码校验

 	@PostMapping("/reset/password")
    public Result resetPassword(@RequestBody ResetPasswordDTO dto) {
        return resetPasswordService.resetPassword(dto);
    }
	@Override
    @Transactional(rollbackFor = Exception.class)
    public Result resetPassword(ResetPasswordDTO dto) {
        Optional<String> oToken = Optional.ofNullable(identifyingCodeService.getCode(USER_REGISTER_PASSWORD,
                dto.getTokenId()));
        if (oToken.isPresent()) {
            if (oToken.get().equals(dto.getCode())) {
                //验证成功,进行操作
                
                //清除验证码
                identifyingCodeService.clean(USER_REGISTER_PASSWORD, dto.getTokenId());
                return  RespUtil.success();
            } else {
                return RespUtil.error(ResultEnum.OPRATOR_FAIL.getCode(),"短信验证码错误.");
            }
        } else {
            return RespUtil.error(ResultEnum.OPRATOR_FAIL.getCode(),"短信验证码错误.");
        }
    }
/**
 * @author author 
 * @since 2020-09-01
 */
@Data
public class ResetPasswordDTO implements Serializable {

    /**
     * 验证码
     */
    private String code;

    /**
     * 验证码id
     */
    private String tokenId;

}

标签:和校验,code,return,String,tokenId,验证码,aliyun,type,public
来源: https://blog.csdn.net/weixin_38006002/article/details/120652515

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有