进入阿里云搜索短信就有对应的短信服务,支付宝购买后进入短信控制台,会有对应的短信服务等信息。包括国内学习、业务统计、系统设置等。
注意:签名和模板不支持个人用户申请未上线业务
2.控制台测试
填写对应信息即可,手机就会收到验证码信息。
因为之前做oss对象存储的时候已经获取过AccessKey和secret-key,所以需要在用户中绑定并授权短信服务即可。
首先看下官方文档的介绍与说明。
com.aliyun
dysmsapi20170525
2.0.18
spring.cloud.nacos.discovery.server-addr:nacos服务注册地址
alicloud.secrect-key:密钥
alicloud.access-key:密钥
sms.endpoint:地域节点
sms.templateCode:模板
其实就是把官方文档的代码拿过来自己用。
@Component
@Data
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms") //和配置文件绑定
public class SmsComponent {
// private String host;
// private String path;
// private String templateId;
// private String appcode;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;
@Value("${spring.cloud.alicloud.secret-key}")
private String accessKey;
/**
* 配置文件对应的
*/
private String endpoint;
private String templateCode;
//
public void sendSmsCode(String phone,String code) throws Exception {
//
//
// String method = "POST";
//
// Map headers = new HashMap();
// //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
// headers.put("Authorization", "APPCODE " + appcode);
// //根据API的要求,定义相对应的Content-Type
// headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
// Map querys = new HashMap();
// Map bodys = new HashMap();
// bodys.put("mobile", phone);
// bodys.put("tag", code);
// bodys.put("templateId", templateId);
//
//
// try {
//
// HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
// System.out.println(response.toString());
// //获取response的body
// System.out.println(EntityUtils.toString(response.getEntity()));
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
Config config = new Config()
// 您的 AccessKey ID
.setAccessKeyId(accessId)
// 您的 AccessKey Secret
.setAccessKeySecret(accessKey);
// 访问的域名
config.endpoint = endpoint;
Client client = new Client(config);
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setSignName("阿里云短信测试")
.setTemplateCode(templateCode)
.setPhoneNumbers(phone)
.setTemplateParam("{\"code\":\""+code+"\"}");
RuntimeOptions runtime = new RuntimeOptions();
SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
System.out.println(sendSmsResponse);
}
}
@ResponseBody
@GetMapping("/sms/sendCode")
public R sendCode(@RequestParam("phone") String phone) throws Exception {
String redisCode = stringRedisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phone);
if (!StringUtils.isEmpty(redisCode)) {
long currentTime = Long.parseLong(redisCode.split("_")[1]);
//系统时间减去当前时间小于60s不能发送
if (System.currentTimeMillis() - currentTime < 60000) {
return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
}
}
//接口防刷
//验证码的再次校验 redis保存 存key->手机号 value->验证码 sms:code:1234567898--->123456
String code = UUID.randomUUID().toString().substring(0, 5);
String subString = code + "_" + System.currentTimeMillis();
//redis缓存验证码 防止同一个手机号在60s内再次发送验证码
stringRedisTemplate.opsForValue().set(AuthConstant.SMS_CODE_CACHE_PREFIX + phone, subString, 10, TimeUnit.MINUTES);
feignService.sendCode(phone, code);
return R.ok();
}
需要将前端传递的手机号进行发送短信收取验证码判断,如果redis中为空调取短信发送服务(通过feign),如果redis不为空,判断系统时间减去当前时间小于60s不能发送,这样有效防止接口防刷恶意操作。前端注册通过手机号调起后端接口,后端通过uuid等技术生成验证码并调取短信服务接口,使用户收取验证码。
Message Digest algorithm 5,信息摘要算法
@Test
void contextLoads() {
// e10adc3949ba59abbe56e057f20f883e
// md5不能直接用来存储加密密码
//可破解 值一直不变 抗修改性: 利用彩虹表 暴力破解法
// 盐值加密
// String s = DigestUtils.md5Hex("123456");
// System.out.println(s);
//
// //加盐:$1$+八位字符 每次盐值加密不一样
// String s1 = Md5Crypt.md5Crypt(s.getBytes(),"$1$qwertyui");//$1$qwertyui$vP2GtrM4.h4RUK.3HGS9J.
// System.out.println(s1);//
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("123456");
// $2a$10$1lc96GWrG7.Lte4f9FsniOAUbpc4t4oaPhXpyG3OiLAxrfsjXqdB6
// $2a$10$2gXOTIfzQDw4VYKhKWNWreNUxCiySPnhAhJiCVLTaXyo6vlPGDPbS
boolean matches = bCryptPasswordEncoder.matches("123456", "$2a$10$2gXOTIfzQDw4VYKhKWNWreNUxCiySPnhAhJiCVLTaXyo6vlPGDPbS");
System.out.println(encode+"========>"+matches);
}
encode产生的和123456始终都会匹配。
@Override
public MemberEntity login(MemberLoginVo vo) {
//获取用户名
String loginAccount = vo.getLoginAccount();
//获取用户的密码
String pagePassword = vo.getPassword();
//去数据库查询
MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper().eq("username", loginAccount).or().eq("mobile", loginAccount));
if (memberEntity == null) {
//登录失败
return null;
} else {
//从数据库返回的密码字段值
String password = memberEntity.getPassword();
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//用页面提交的代码和数据库注册的盐值进行匹配
boolean b = passwordEncoder.matches(pagePassword, password);
if (b) {
return memberEntity;
} else {
return null;
}
}