如何使用阿里云短信服务实现登录页面,手机验证码登录?1

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 如何使用阿里云短信服务实现登录页面,手机验证码登录?

1:个人如何使用阿里云短信服务?

2022如何使用个人阿里云短信服务?_linxiMY的博客-CSDN博客

添加完成之后,等待审核!一般2个小时就会出来审核结果了,这里我因为注册申请时填写规则有误,足足审核了7次才通过!点击进来以后,按照要求填写:因为一个账号只能选购一种,所以我这里就没法仔细演示了。然后点击添加即可,一把2-3个小时就可以申请出结果了。ConstantPropertiesUtils 工具类。点击登录阿里云短信服务控制台--->点击。3:创建一个SpringBoot 启动类。将下面的服务地址改为自己对应的地址。AccessKey 保存下来!4:添加一个配置工具类类。开启启动类调接口测试。

https://blog.csdn.net/XikYu/article/details/127617049?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168232320316800192242795%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=168232320316800192242795&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-127617049-null-null.blog_rank_default&utm_term=%E9%98%BF%E9%87%8C%E4%BA%91&spm=1018.2226.3001.4450

2:直接上代码

2.1:建表SQL

CREATE TABLE `sys_user`
(
    `id`          varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'id',
    `username`    varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
    `password`    varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '密码',
    `nickname`    varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '昵称',
    `email`       varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '邮箱',
    `phone`       varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '电话',
    `address`     varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '地址',
    `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `avatarUrl`   varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '头像',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.2:后端代码

引入pom.xml 依 赖:

<dependencies>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
    </dependency>
</dependencies>

yml 文件:

server:
  port: 9999
spring:
  application:
    name: demo-end
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/数据库?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: root
  redis:
    host: ip地址
    port: 6379
    lettuce:
      pool:
        max-active: 8 # ????
        max-idle: 8 # ??????
        min-idle: 0 # ??????
        max-wait: 100ms # ??????
mybatis:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.xi.demoend.entity

application.properties:

aliyun.sms.regionId=default
aliyun.sms.accessKeyId=xxxxxx
aliyun.sms.secret=xxxxxx

common公共包下的类:

全局统一返回结果:

package com.xialj.demoend.common;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
 * @Author 
 * @Date Created in  2023/2/23 17:25
 * @DESCRIPTION:  全局统一返回结果
 * @Version V1.0
 */
@Data
@ApiModel(value = "全局统一返回结果")
@SuppressWarnings("all")
public class Result<T> {
    @ApiModelProperty(value = "返回码")
    private Integer code;
    @ApiModelProperty(value = "返回消息")
    private String message;
    @ApiModelProperty(value = "返回数据")
    private T data;
    private Long total;
    public Result(){}
    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;
    }
    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }
    public static <T> Result<T> build(Integer code, String message) {
        Result<T> result = build(null);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
    public static<T> Result<T> ok(){
        return Result.ok(null);
    }
    /**
     * 操作成功
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }
    public static<T> Result<T> fail(){
        return Result.fail(null);
    }
    /**
     * 操作失败
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.FAIL);
    }
    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }
    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }
    public boolean isOk() {
        if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
            return true;
        }
        return false;
    }
}

统一返回结果状态信息类:

package com.xialj.demoend.common;
import lombok.Getter;
/**
   * @Author 
   * @Date Created in  2023/2/23 17:25
   * @DESCRIPTION:  统一返回结果状态信息类
   * @Version V1.0
   */
@Getter
@SuppressWarnings("all")
public enum ResultCodeEnum {
    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    PARAM_ERROR( 202, "参数不正确"),
    SERVICE_ERROR(203, "服务异常"),
    DATA_ERROR(204, "数据异常"),
    DATA_UPDATE_ERROR(205, "数据版本异常"),
    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),
    CODE_ERROR(210, "验证码错误"),
//    LOGIN_MOBLE_ERROR(211, "账号不正确"),
    LOGIN_DISABLED_ERROR(212, "改用户已被禁用"),
    REGISTER_MOBLE_ERROR(213, "手机号码格式不正确"),
    REGISTER_MOBLE_ERROR_NULL(214, "手机号码为空"),
    LOGIN_AURH(214, "需要登录"),
    LOGIN_ACL(215, "没有权限"),
    URL_ENCODE_ERROR( 216, "URL编码失败"),
    ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),
    FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),
    FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),
    //LOGIN_ERROR( 23005, "登录失败"),
    PAY_RUN(220, "支付中"),
    CANCEL_ORDER_FAIL(225, "取消订单失败"),
    CANCEL_ORDER_NO(225, "不能取消预约"),
    HOSCODE_EXIST(230, "医院编号已经存在"),
    NUMBER_NO(240, "可预约号不足"),
    TIME_NO(250, "当前时间不可以预约"),
    SIGN_ERROR(300, "签名错误"),
    HOSPITAL_OPEN(310, "医院未开通,暂时不能访问"),
    HOSPITAL_LOCK(320, "医院被锁定,暂时不能访问"),
    HOSPITAL_LOCKKEY(330,"医院对应key不一致")
    ;
    private Integer code;
    private String message;
    private ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

untils包下的工具类:

ConstantPropertiesUtils 用来读取 application.properties文件中的配置

package com.xialj.demoend.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @Author 
 * @Date Created in  2023/2/23 17:25
 * @DESCRIPTION:
 * @Version V1.0
 */
@Component
public class ConstantPropertiesUtils implements InitializingBean {
    //InitializingBean  初始化bean  让spring 容器一初始化就加载
    @Value("${aliyun.sms.regionId}")
    private String regionId;
    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.sms.secret}")
    private String secret;
    public static String REGION_Id;
    public static String ACCESS_KEY_ID;
    public static String SECRECT;
    @Override
    public void afterPropertiesSet() throws Exception {
        REGION_Id=regionId;
        ACCESS_KEY_ID=accessKeyId;
        SECRECT=secret;
    }
}

RandomUtil 工具类用来生成6位验证码:

package com.xialj.demoend.utils;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
/**
 * @Author 
 * @Date Created in  2023/2/23 17:25
 * @DESCRIPTION:
 * @Version V1.0
 */
@SuppressWarnings("ALL")
public class RandomUtil {
    private static final Random random = new Random();
    private static final DecimalFormat fourdf = new DecimalFormat("0000");
    private static final DecimalFormat sixdf = new DecimalFormat("000000");
    public static String getFourBitRandom() {
        return fourdf.format(random.nextInt(10000));
    }
    public static String getSixBitRandom() {
        return sixdf.format(random.nextInt(1000000));
    }
    /**
     * 给定数组,抽取n个数据
     * @param list
     * @param n
     * @return
     */
    public static ArrayList getRandom(List list, int n) {
        Random random = new Random();
        HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
// 生成随机数字并存入HashMap
        for (int i = 0; i < list.size(); i++) {
            int number = random.nextInt(100) + 1;
            hashMap.put(number, i);
        }
// 从HashMap导入数组
        Object[] robjs = hashMap.values().toArray();
        ArrayList r = new ArrayList();
// 遍历数组并打印数据
        for (int i = 0; i < n; i++) {
            r.add(list.get((int) robjs[i]));
            System.out.print(list.get((int) robjs[i]) + "\t");
        }
        System.out.print("\n");
        return r;
    }
}

User实体类:(实现了简单的手机验证码登录+email邮箱登录)

package com.xialj.demoend.entity;
import com.alibaba.druid.sql.visitor.functions.Insert;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * @Author 
 * @Date Created in  2023/2/24 13:07
 * @DESCRIPTION:   User 实体类
 * @Version V1.0
 */
@Data
public class User extends PageQuery implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    private String id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 昵称
     */
    private String nickname;
    /**
     * 邮箱
     */
    @ApiModelProperty(value = "联系人邮箱")
    @NotBlank(message = "邮箱不能为空", groups = {Insert.class})
    @NotNull(message = "邮箱不能为空", groups = {Insert.class})
    @Pattern(regexp = ".+@.+\\.com$", message = "Email格式不正确")
    private String email;
    /**
     * 电话
     */
    @ApiModelProperty(value = "联系人电话")
    @NotBlank(message = "手机号码不能为空", groups = {Insert.class})
    @NotNull(message = "手机号不能为空", groups = {Insert.class})
    @Length(min = 11, max = 11, message = "手机号只能为11位")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
    private String phone;
    /**
     * 地址
     */
    private String address;
    /**
     * 验证码
     */
    private Integer code;
    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date createTime;
    /**
     * 头像
     */
    private String avatarUrl;
}

MsmApiController:用来实现发送验证码的接口

package com.xialj.demoend.controller;
import cn.hutool.extra.mail.MailUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xialj.demoend.common.Result;
import com.xialj.demoend.common.ResultCodeEnum;
import com.xialj.demoend.common.paramCommon;
import com.xialj.demoend.entity.User;
import com.xialj.demoend.service.MsmService;
import com.xialj.demoend.utils.JsonSerializer;
import com.xialj.demoend.utils.RandomUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.mail.MessagingException;
import javax.validation.constraints.Email;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
 * @Author xlj
 * @Date Created in  2023/2/23 17:25
 * @DESCRIPTION:  主要是为了实现邮箱发送验证码,以及手机发送验证码登录
 * @Version V1.0
 */
@RestController
@RequestMapping("/api/msm")
@SuppressWarnings("ALL")
@Slf4j
@CrossOrigin
public class MsmApiController {
    @Autowired
    private MsmService msmService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    //将手机验证码存放到redis  中,并设置过期时间
    @ApiOperation(value = "发送手机验证码")
    @PostMapping("sendPhoneCode")
    public Result sendCode(@RequestBody(required = true) @Validated User user){
        String phoneNum = user.getPhone();
        // phone  作为redis  中的key,  code  作为redis  中的value值
        String code = redisTemplate.opsForValue().get(phoneNum);
        if (!StringUtils.isEmpty(code)) {
            //这里为什么从redis 拿取 验证码  我理解的是 ,因为redis 验证码我们给他设置了时间限制,所以在规定时间内,验证码
            //可以多次使用,一旦时间到期之后,我们就需要从新生成6位数的验证码了。
            return Result.ok(code);
        }
        //生成六位验证码
        code = RandomUtil.getSixBitRandom();
        //调用service 方法,整合阿里云短信服务进行发送
        Boolean isSend = msmService.send(phoneNum,code);
        //返回的Boolean 值进行判断 ,如果发送信息成功,即存入到redis 中,如果没有则提示验证码发送失败
        if (isSend) {
            //放到redis中规定时间内有效
            redisTemplate.opsForValue().set(phoneNum,code,1, TimeUnit.MINUTES);
            redisTemplate.setDefaultSerializer(new JsonSerializer<>());
//            redisTemplate.opsForValue().set(phoneNum,code);
            String codeMessage = redisTemplate.opsForValue().get(phoneNum);
            Set<String> allKeys = redisTemplate.keys("*");
            for (String key : allKeys) {
                System.out.println(key);
                System.out.println(key.getClass().getName());
            }
            log.info("当前存储的验证码为:{}",codeMessage);
            return Result.ok(code);
        } else {
            return Result.fail().message(paramCommon.FAIL_MESSAGE);
        }
    }
}

MsmServiceImpl实现类:

package com.hospital.service.impl;
import com.alibaba.fastjson.JSONObject;
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;
import com.hospital.service.MsmService;
import com.hospital.utils.ConstantPropertiesUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
@Service
public class MsmServiceImpl implements MsmService {
    //根据手机号,存入验证码
    @Override
    public Boolean send(String phone, String code) {
        //判断手机号是否为空
        if (StringUtils.isEmpty(phone)) {
            return false;
        }
        //整合阿里云的短信服务
        DefaultProfile profile = DefaultProfile.
                getProfile(ConstantPropertiesUtils.REGION_Id,
                        ConstantPropertiesUtils.ACCESS_KEY_ID,
                        ConstantPropertiesUtils.SECRECT);
        IAcsClient client = new DefaultAcsClient(profile);
        CommonRequest request = new CommonRequest();
        //request.setProtocol(ProtocolType.HTTPS);
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");
//        request.setSysAction();
        //手机号
        request.putQueryParameter("PhoneNumbers", phone);
        //签名名称
        request.putQueryParameter("SignName", "自己申请的短信签名");
        //模板code
        request.putQueryParameter("TemplateCode", "短信模板CODE");
        //验证码  使用json格式   {"code":"123456"}
        Map<String,Object> param = new HashMap();
        param.put("code",code);
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));
        //调用方法进行短信发送
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            return response.getHttpResponse().isSuccess();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return false;
    }
}


目录
相关文章
|
2月前
|
云安全 安全 API
阿里云——OpenAPI使用——短信服务
阿里云——OpenAPI使用——短信服务
155 0
|
2月前
|
弹性计算 Windows
使用阿里云服务器登录雾锁王国后,游戏创建失败怎么办
使用阿里云服务器登录雾锁王国后,游戏创建失败时,请更新游戏并重启游戏进程。
284 3
|
2月前
|
存储 安全
阿里云网盘与相册问题之账户登录不上如何解决
阿里云网盘与相册是阿里云提供的云存储服务,用户可以安全便捷地存储和管理个人文件、照片等数据;本合集将介绍如何使用阿里云网盘和相册服务,包括文件上传、同步、分享,以及处理常见使用问题的技巧。
45 2
|
2月前
|
存储 缓存 安全
阿里云网盘与相册问题之如何解除限制境外IP登录
阿里云网盘与相册是阿里云提供的云存储服务,用户可以安全便捷地存储和管理个人文件、照片等数据;本合集将介绍如何使用阿里云网盘和相册服务,包括文件上传、同步、分享,以及处理常见使用问题的技巧。
42 0
|
2月前
|
存储 监控 安全
阿里云云通信短信服务安全之安全架构
阿里云云通信长期致力于通过多种渠道向客户透明服务相关情况。客户一般可通过阿里云官网提出对阿里云云通信相关资质、服务使用情况、产品说明等信息,我们将7*24小时不间断处理您的建议与咨询。对于客户合理的要求,阿里云云通信服务团队均会及时响应客户的需求。同时,阿里云云通信也在探索更多增加透明度的方式,如对公邮箱、线上查询接口、钉钉服务客户群等。
|
2月前
|
运维 监控 安全
阿里云云通信短信服务安全之安全责任共担与安全合规
阿里云云通信长久以来致力于为客户提供稳定可靠、安全可信、合法合规的通信服务,利用先进技术、建立产品体系、严格管理人员等不同手段以保护客户及合作伙伴数据的机密性、完整性、可用性,以数据安全、用户隐私保护作为阿里云云通信的最高准则。
|
3月前
|
JSON 开发工具 数据格式
App Inventor 2 接入阿里云短信服务,实现短信验证码功能
App Inventor 2 接入阿里云短信服务,实现短信验证码功能:发送短信验证码功能一般都是基于短信平台提供的sdk进行调用,这里是基于阿里云短信平台进行的开发。
115 1
|
4月前
|
Java Maven
(短信服务)java SpringBoot 阿里云短信功能实现发送手机验证码
(短信服务)java SpringBoot 阿里云短信功能实现发送手机验证码
669 0
|
4月前
|
安全
阿里云短信服务是可以发送包含下载链接的文本内容的,
阿里云短信服务是可以发送包含下载链接的文本内容的,但是需要注意以下几点:
227 1
|
7月前
|
存储 弹性计算 JavaScript
基于阿里云短信服务的防机器人验证
基于阿里云相关产品和服务实现一个手机验证码登录的功能,防止机器人批量注册,服务端采用阿里云ECS服务器,程序语言选用JAVA,服务器软件选用Tomcat,应用服务采用阿里云短信服务,
186 0

热门文章

最新文章