1. 程式人生 > 其它 >12.認證服務-簡訊驗證碼

12.認證服務-簡訊驗證碼

一、阿里雲簡訊服務

https://www.aliyun.com/product/sms?spm=5176.159202.J_8058803260.68.64ae6a56APLp1H

二、工具類 HttpUtils

HttpUtils 請從 https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java

或者直接下載:http://code.fegine.com/HttpUtils.zip

下載相應的依賴請參照 https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml

相關jar包(非pom)直接下載:http://code.fegine.com/aliyun-jar.zip

三、相關配置

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.163.131:8848
    alicloud:
      sms:
        host: https://fesms.market.alicloudapi.com
        path: /sms/
        skin: 1
        sign: 175622
        appcode: 93b7e19861a24c519a7548b17dc16d75

 

四、傳送驗證碼元件

package com.zsy.third.party.component;

import com.zsy.common.utils.HttpUtils;
import lombok.Data;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @author: zhangshuaiyin
 * @createTime: 2020-06-27 09:39
 **/
@ConfigurationProperties(prefix = "spring.cloud.alicloud.sms")
@Data
@Component
public class SmsComponent {

    private String host;
    private String path;
    private String skin;
    private String sign;
    private String appcode;

    public void sendCode(String phone, String code) {
        String method = "GET";
        Map<String, String> headers = new HashMap<>();
        // 最後在header中的格式(中間是英文空格)為 Authorization:APPCODE 93b7e19861a24c519a7548b17dc16d75
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> queries = new HashMap<String, String>();
        queries.put("code", code);
        queries.put("phone", phone);
        queries.put("skin", skin);
        queries.put("sign", sign);
        //JDK 1.8示例程式碼請在這裡下載:  http://code.fegine.com/Tools.zip
        try {
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, queries);
            //System.out.println(response.toString());如不輸出json, 請開啟這行程式碼,列印除錯頭部狀態碼。
            //狀態碼: 200 正常;400 URL無效;401 appCode錯誤; 403 次數用完; 500 API網管錯誤
            //獲取response的body
            System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

五、測試

@Test
    public void sendSmsCode() {
        smsComponent.sendCode("13838383838", "134531");
    }

六、傳送簡訊介面

/**
 * @author: zhangshuaiyin
 * @createTime: 2020-06-27 10:04
 **/
@Controller
@RequestMapping(value = "/sms")
public class SmsSendController {

    @Resource
    private SmsComponent smsComponent;

    /**
     * 提供給別的服務進行呼叫
     * @param phone
     * @param code
     * @return
     */
    @GetMapping(value = "/sendCode")
    public R sendCode(@RequestParam("phone") String phone, @RequestParam("code") String code) {
        //傳送驗證碼
        smsComponent.sendCode(phone,code);
        return R.ok();
    }
}

七、介面防刷和驗證碼再次校驗

mall-auth-server LoginController.java

@ResponseBody
@GetMapping(value = "/sms/sendCode")
public R sendCode(@RequestParam("phone") String phone) {

    //1、介面防刷
    String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
    if (!StringUtils.isEmpty(redisCode)) {
        //活動存入redis的時間,用當前時間減去存入redis的時間,判斷使用者手機號是否在60s內傳送驗證碼
        long currentTime = Long.parseLong(redisCode.split("_")[1]);
        if (System.currentTimeMillis() - currentTime < 60000) {
            //60s內不能再發
            return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
        }
    }

    //2、驗證碼的再次效驗 redis.存key-phone,value-code
    int code = (int) ((Math.random() * 9 + 1) * 100000);
    String codeNum = String.valueOf(code);
    String redisStorage = codeNum + "_" + System.currentTimeMillis();

    //存入redis,防止同一個手機號在60秒內再次傳送驗證碼
    stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone,
                                          redisStorage, 10, TimeUnit.MINUTES);

    thirdPartFeignService.sendCode(phone, codeNum);

    return R.ok();
}