阿里大于短信——发送手机验证码

使用阿里大于的短信服务需要先去开通相应服务,具体过程:https://www.jb51.net/article/171902.htmhttps://www.cnblogs.com/shubs/p/12092089.html

加依赖:
 

<!--阿里大于短信-->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>4.5.3</version>
        </dependency>

然后拿到下面几个参数:

1、密钥:AccessKeyId、AccessKeySecret

2、模板CODE

3、短信签名(2和3在阿里云官网设置)

可以先去官网的OpenAPI Explorer中测试是否成功:

信息填好发送返回成功即可

再去看看官网是怎么发送请求的:

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
/*
pom.xml
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-core</artifactId>
  <version>4.5.3</version>
</dependency>
*/
public class SendSms {
    public static void main(String[] args) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<accessKeyId>", "<accessSecret>"); //密钥
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        try {
//模板CODE、手机、签名等都在request中
            CommonResponse response = client.getCommonResponse(request); 
            System.out.println(response.getData());
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }
}

发现很简单,我们就是把一些参数封装进request中,其他基本可以照抄:
 

@Slf4j
public class SendSmsUtils {

    // 阿里云API密钥,注意空格
    private static String accessKeyId = "LTAI4FrRvd4jiP4EHy782";
    private static String accessSecret = "w7mImDkpvVorcKLL";
    //模板
    private static String templateCode= "SMS_202550742";
    //签名
    private static String signName = "ABC商城";

    /**
     *
     * @param phoneNumber 接收手机号,可多个,验证码发送最好只一个手机号
     * @param signName 签名名称
     * @param templateCode 模板CODE
     * @param templateParam 模板参数,JSON字符串{code:123567}
     */
    public static String SendMessage(String phoneNumber,String templateParam){
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        // 接收手机号码,多个以逗号隔开
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        // 签名名称
        request.putQueryParameter("SignName", signName);
        // 模板CODE
        request.putQueryParameter("TemplateCode", templateCode);
        // 模板缺失内容
        request.putQueryParameter("TemplateParam", templateParam);
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            return response.getData();
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (ClientException e) {
            e.printStackTrace();
            return null;
        }
    }



}

这样我们在controller中调用该方法即可发送成功:
 

    @Autowired
    SmsService smsService;


    @ApiOperation("获取手机验证码")
    @GetMapping("/sms")
    @ApiImplicitParam(value = "手机号",name = "phone",required = true,dataType = "string",paramType = "query")
    public String getSMSCode(@RequestParam("phone") String phone){
        //向验证码服务请求发送验证码
        return smsService.sendMsg(phone);
    }

上面是一个简单的发送验证码的例子,验证码一般是用于登陆/注册时用到,而真实的项目,可以在接到请求时在后台生成验证码,然后将其放到redis中(设置过期时间),在用户收到验证码时则填写完发到后端,此时再去和redis中的验证码进行对比。

然而这样还是有多个问题需要考虑:
1、前端中请求验证码的接口暴露,可能被恶意刷接口

2、用户多次请求,重复请求(接口幂等性)

3、换ip/手机去刷

前端控制每60分钟发送一次,在接口调用时添加图形验证码(在提交时增加图片验证码来限制机器请求,一般图片验证码可以防止大部分的机器刷码)、单ip请求限制、限定每天每个号码获取短信验证码的次数、限制短信验证码的调用频率等 

正常用户重复请求可以前端控制60s一次就可以了,也可以利用token机制,在前端和后端(redis)放同一个码,每次请求过来检验通过才给发验证码。

如果使用token机制还需要考虑另一个点,当数据要求比较严格时,如订单提交的幂等性,此时如果系统是分布式,考虑到并发高、且数据要求严格,此时则要对其token加上分布式锁,以保证只有一个进程拿到redis中的token并进行后面的操作。

当然一个接口保证幂等性除了token机制,还可以在后端维护一个重复表,每次请求来看下有没有重复的,重复的则不进行处理,

还有一些对数据库的操作本身是具有幂等性的,如查询,更新删除时不对值进行增量计算(例不要用a+=2,或-1等变量操作)

!!!!!!!!!!!!!!!!!扯太远了

(如果是订单的别忘了要考虑分布式事务的处理啊)

https://blog.csdn.net/weixin_42023666/article/details/89680342

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值