SpringBoot 通过阿里云的短信功能 实现发送手机验证码

我们在项目中经常遇到 需要通过手机号发送验证码实现登录注册等功能。
这里讲一下,Springboot项目中如果通过阿里云的短信功能, 实现发送手机验证码并验证

一、准备工作

1、购买阿里云的短信服务

https://free.aliyun.com/product/cloudcommunication-free-trial

新用户有免费试用产品

个人使用的话,有3个月内100条的免费服务,如果学习的话,足够用了,否则还需要充钱!!!
在这里插入图片描述

2、购买后,设置 AccessKey
在这里插入图片描述
在这里插入图片描述
阿里云会自动获取绑定的手机号,你只需要获取短信验证码就可以创建成功。
在这里插入图片描述
3、设置签名
在这里插入图片描述
在这里插入图片描述

4、添加模板
在这里插入图片描述
在这里插入图片描述

开发

开发者可以按照阿里云的这个开发者手册开发。

https://help.aliyun.com/document_detail/101300.html?spm=a2c4g.11186623.6.610.5ed850a4DjrhHY

发送短信这个接口如何调用? 这个网址还提供了调试功能,很方便。

https://help.aliyun.com/document_detail/101414.html?spm=a2c4g.11186623.6.624.15b85f30AyGxea


我们可以直接调用 阿里云为我们提供的API

这里只用自定义的方法

1、导入依赖

<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-core</artifactId>
   <version>4.5.3</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>1.1.0</version>
</dependency>

2、编写工具类

这里自定义工具类进行使用

/**
 * description:
 *
 * @author su
 * @date 2022/2/15 14:41
 */
@Component
public class SMSUtils {

	private static final Logger log = LoggerFactory.getLogger(SMSUtils.class);
	@Value("${sms.accessKeyId}")
	private String accessKeyId;
	@Value("${sms.secret}")
	private String secret;
	@Value("${sms.signName}")
	private String signName; // 短信签名
	@Value("${sms.templateCode}")
	private String templateCode;  //短信模板
	@Value("${sms.regionId}")
	private String regionId;   // 短信服务器区域


	public void sendMsg(String phone, String code) {

		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, secret);
		DefaultAcsClient client = new DefaultAcsClient(profile);
		CommonRequest request = new CommonRequest();

		request.setSysMethod(MethodType.POST);
		//下面两个不能动
		request.setSysProduct("Dysmsapi");
		request.setSysDomain("dysmsapi.aliyuncs.com");
		
		request.setSysVersion("2017-05-25");
		request.setSysAction("SendSms");
		//自定义参数(手机号,验证码,签名,模板)
		request.putQueryParameter("RegoinId", regionId);
		request.putQueryParameter("PhoneNumbers", phone);
		request.putQueryParameter("SignName", signName); //填自己申请的名称
		request.putQueryParameter("TemplateCode", templateCode);
		request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");

		try {
			CommonResponse response = client.getCommonResponse(request);
			log.info("阿里云短信响应信息:" + response.getData());
			boolean success = response.getHttpResponse().isSuccess();
			log.info("短信发送是否成功:" + success);
		} catch (ClientException e) {
			e.printStackTrace();
		}
	}
}

这些变量放在配置文件中,方便维护

sms:
  accessKeyId: LTAI5tGF2kkoJbB9ftdH2DwT
  secret: YYc2CShh6RVZmMuhQzifAXS5WimvuI
  signName: 青橙小店
  templateCode: SMS_217145407
  regionId: cn-hangzhou
@RestController
@RequestMapping("admin")
public class UserController {
	private static final Logger log = LoggerFactory.getLogger(UserController.class);

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	public SMSUtils smsUtils;


	@PostMapping("/code")
	public void sendMsg(@RequestBody MsgVo msgVo) {
		if (redisTemplate.hasKey("TOMEOUT:" + msgVo.getPhone())) {
			throw new RuntimeException("不允许重复发送");
		}
		String code = RandomStringUtils.randomNumeric(4);
		log.info("发送的验证码:{}" + code);
		smsUtils.sendMsg(msgVo.getPhone(), code);

		redisTemplate.opsForValue().set(msgVo.getPhone(), code, 60, TimeUnit.SECONDS);
		redisTemplate.opsForValue().set("TOMEOUT:" + msgVo.getPhone(), true, 10, TimeUnit.MINUTES);
	}
}

启动测试
在这里插入图片描述

  • 10
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现用户手机验证码登录可以分为以下几个步骤: 1. 用户输入手机号和验证码,点击登录按钮。 2. 后端接收到手机号和验证码后,先验证验证码是否正确。 3. 如果验证码正确,后端生成JWT token并将token存储到Redis中,同时将token返回给前端。 4. 前端将token存储到本地,以便后续请求时使用。 5. 后续请求时,前端需要在请求头中加入token,后端通过解析token来判断用户是否已登录。 下面是具体实现过程: 1. 在阿里云短信控制台创建短信模板,获取accessKeyId和accessKeySecret。 2. 在Spring Boot项目中添加依赖: ``` <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.0.3</version> </dependency> ``` 3. 实现发送短信验证码的接口: ``` @PostMapping("/sendSms") public Result sendSms(@RequestParam("phone") String phone) { // 生成随机验证码 String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000)); // 发送短信验证码 DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret); 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", phone); request.putQueryParameter("SignName", "短信签名"); request.putQueryParameter("TemplateCode", "短信模板编号"); request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}"); try { CommonResponse response = client.getCommonResponse(request); // 将验证码存储到Redis中,有效期为5分钟 redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES); return Result.success("短信验证码发送成功"); } catch (Exception e) { return Result.error("短信验证码发送失败"); } } ``` 4. 实现用户手机验证码登录的接口: ``` @PostMapping("/login") public Result login(@RequestParam("phone") String phone, @RequestParam("code") String code) { // 验证验证码是否正确 String redisCode = redisTemplate.opsForValue().get(phone); if (StringUtils.isBlank(redisCode)) { return Result.error("验证码已过期,请重新发送"); } if (!redisCode.equals(code)) { return Result.error("验证码不正确"); } // 生成JWT token,并存储到Redis中 String token = JwtUtils.generateToken(phone); redisTemplate.opsForValue().set(phone, token, 1, TimeUnit.DAYS); // 将token返回给前端 return Result.success(token); } ``` 5. 实现JWT token的生成和解析: ``` public class JwtUtils { private static final String SECRET_KEY = "jwt_secret_key"; // JWT密钥 private static final long EXPIRATION_TIME = 7 * 24 * 60 * 60 * 1000; // JWT过期时间(7天) public static String generateToken(String phone) { Date now = new Date(); Date expiration = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(phone) .setIssuedAt(now) .setExpiration(expiration) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getPhoneFromToken(String token) { try { Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); return claims.getSubject(); } catch (Exception e) { return null; } } } ``` 6. 在拦截器中验证token并获取用户信息: ``` public class JwtInterceptor implements HandlerInterceptor { private static final String AUTH_HEADER = "Authorization"; // token在请求头中的名称 @Autowired private StringRedisTemplate redisTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader(AUTH_HEADER); if (StringUtils.isBlank(token)) { throw new BusinessException("未登录或登录已过期"); } String phone = JwtUtils.getPhoneFromToken(token); if (StringUtils.isBlank(phone)) { throw new BusinessException("无效的token"); } String redisToken = redisTemplate.opsForValue().get(phone); if (StringUtils.isBlank(redisToken) || !redisToken.equals(token)) { throw new BusinessException("未登录或登录已过期"); } return true; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值