最近课程项目做一个网站,需要实现注册、忘记密码等功能的推送验证码的功能
而且根据相关法律法规,用户也需要手机号认证…(反正很多网站都是这么说的)
本来想弄一个免费的短信服务商,http://www.mob.com/product/sms这家就挺不错的,支持还挺全,有
而且都是免费的!
但是没有web
端
客服回答说要有APP,要上线,要充值,每条五分…瞬间没了好感
而且不管使用什么SDK都要实名认证,身份证照片啊,手持身份证照片啊,说实话把这些信息给这些小企业有点信不过
开始准备看看他们提供的Android
源码,你不也是调用API
去发送短信吗,那我就把这个接口给 偷过来 窃过来不就可以了
当我一层一层地点开各种方法时,看到的都是类似下图这种a
啊,b
啊的方法名,还有参数也不明白意思,看来做了混淆防止反编译,算了,我这点渣渣水平就不去像这种骚操作了。
如果真的不想花钱的话,可以找一台手机(安卓或IOS)使用它们的SDK,然后从网站上去唤醒这个手机发送验证码的功能,间接使用,当然速度会很慢啊,手机一直联网可能会断网啊,增加开发手机端的代码量啊很多缺点,但是不要钱也是很香的
还是决定老老实实用付费的吧
这个选择就多了去了,普遍是0.05
元一条,有的小网站可以做到0.03
元左右,还是用大服务商的吧,稳定信得过,什么阿里云,腾讯云,百度云,网易云啥的都有
这里我选择的是阿里云
顺便说一下,良心的亚马逊云AWS也有免费的短信包,之前我就一直在用这个测试,但是后来才发现只有美国的手机号码才免费,于是花了我0.1美元…
定价如下,可以选择套餐包或者预付费,不过套餐是5000
条起卖225
元(emmmm对于我们这种蚊子型网站有点浪费啊)所以还是选择预付费吧,用多少付多少
而且新开通的用户还会送100条短信
,估计是考虑到测试的需要
开通链接
然后需要两个基本的东西,一个是签名,一个是模板
如下
然后进入控制台->短信服务->国内消息->添加签名,可以看到我已经添加了一条签名
签名填写服务的名称,场景选择验证码(通用类型需要验证很多东西),申请说明是给审核人员看的,一般两小时会完成审核
选择模板管理->添加模板
选择验证码
输入模板名称(这个名称是给自己看的不会出现在短信中)
输入模板内容(可以有变量,用${}包起来,发短信的时候可以动态控制)
还有申请说明
当签名和模板都审核通过后
点击快速学习,使用给定的签名和模板进行测试,填入变量和手机号码,点击发送短息就可以测试发送消息
另外这个查看API Demo会提供各种代码调用API的示例,方便整合进自己的服务中,后面还会用到
使用代码调用API时,要通过accessKeyId
和secret
验证身份
点击右上角个人头像,选择访问控制
为什么是点访问控制而不是
accesskeys
呢?
- 因为
accesskeys
里面也会建议你使用子用户进行访问。那为什么要子用户进行访问呢?
- 比如在阿里云开通了很多付费服务都需要
accesskey
验证,如果使用主账户的accesskey
不小心泄露了,那么所有的付费服务都被泄露了,可能带来很大的财产损失和信息丢失- 如果使用子用户就可以动态控制每个用户的权限,比如a用户只有发短息的权限,再不济泄露了也不会影响其他的服务,将损失降为最小
选择用户->新建用户,可以看到我已经建立了两个用户分别用于短信和邮件服务
写好登录名称,显示名称,勾选编程访问就好了,如果是控制台登录的话其实就相当于一个阿里云账户可以在网站上登录,这个暂时不需要
下图中的AccessKeyID
和AccessKeySceret
就是编程需要的参数了
不要试图使用我的这个
AccessKey
干坏事哦,因为我账户里没钱它已经被删掉啦
需要注意的是账号一旦创建完成,就再也看不到它们了,所以要提前点击复制或者下载CSV文件进行备份
然后再点击添加权限
对于短信推送
输入sms
进行搜索,选择AliyunDysmsFullAccess
,点击确定
回到控制台->短信服务->快速学习,点击查看API DEMO
在右侧选择需要的语言,将代码全部复制下来
以JAVA
为例
因为使用的api
是阿里云自家的,所以官方默认jar
肯定是没有
以maven
为例
在dependencies
中添加依赖,这个依赖在API DEMO中的注释部分给了出来,如
com.aliyun
aliyun-java-sdk-core
4.1.0
//填入有短信推送服务权限的AccessKey id和secret
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "" , "" );
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
//设置https调用
//request.setProtocol(ProtocolType.HTTPS);
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
//设置收信手机号码
request.putQueryParameter("PhoneNumbers", "12233334444");
//之前申请的签名名称
request.putQueryParameter("SignName", "TimeIsMoney");
//之前申请的模板CODE
request.putQueryParameter("TemplateCode", "SMS_165380907");
//模板里面的变量赋值,使用JSON格式
request.putQueryParameter("TemplateParam", "{\"code\":\"6666\"}");
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
如果是开源项目的话,这样子会直接把密钥暴露在互联网中,相当不安全,所以需要做一点措施,把密钥和代码分开
在resources
包里添加包privateKey
在这个包里新建SMSKey.txt
存储密钥
写上两行数据,一行是ID
一行是secret
修改代码,添加两个私有变量accessKeyId
和secret
,并且在静态代码块里把它们赋值为txt
中的值
private static final String accessKeyId;
private static final String secret;
/**
* 初始化获取私钥
* */
static {
ClassPathResource smsKey = new ClassPathResource("privateKey/SMSKey.txt");
System.out.println(smsKey);
Scanner scanner = null;
try {
scanner = new Scanner(smsKey.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
accessKeyId = scanner.nextLine();
secret = scanner.nextLine();
scanner.close();
}
然后调用的时候使用这两个变量就好了
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, secret);
邮件的密钥同理
还有一步,不能把这两个txt
文件也传到git
仓库中去
在gitignore
中添加
EmailKey.txt
SMSKey.txt
现在就可以安心地把代码push
上去了。
另外这只是开源代码遇到的问题,如果真的部署到了服务器,还会有以下问题值得思考
获取验证码的网站页面,没有做防止非法获取验证码的措施,比如最简单的图形校验码。(常见于网站上获取验证码)
建议:点击获取验证码之前做一个校验,比如需要正确输入图形验证码、拖动验证等
发送短信的接口暴露,且没有做加密措施,遭受恶意调用。(此类常见于APP侧获取验证码)
建议:在短信接口做一些加密措施(例如加入图形验证等方式),防止非法调用。