SpringBoot+react/umi實現手機短信驗證登陸功能

點擊上方 java項目開發選擇 設爲星標javascript

優質文章,及時送達前端

--

案例功能效果圖

前端初始頁面vue

點擊獲取驗證碼交互效果頁面java


手機獲取短信驗證碼成功頁面mysql



登陸成功頁面react


登陸成功能夠直接設置跳轉任何頁面
git


環境介紹

前端:umijsgithub

後端:springbootweb

jdk:1.8及以上redis

數據庫:mysql


完整源碼獲取方式



源碼獲取方式

掃碼關注回覆【duanxin】獲取完整源碼


若是你在運行這個代碼的過程當中有遇到問題,請加小編微信xxf960513,我拉你進對應微信學習羣!!幫助你快速掌握這個功能代碼!




核心代碼介紹



pom.xml


      <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-access</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency>
<!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.5.21</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.3</version> </dependency>
<!-- mysql驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version>        </dependency> <!--短信功能須要的jar包依賴--> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>1.1.0</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>    </dependencies></project>

application.properties


server.port=8002#server.servlet.context-path=/spring.datasource.url=jdbc:mysql://xxxxx:3306/xxxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaispring.datasource.username=xxxxxxxxxspring.datasource.password=xxxxxxxxxspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#開啓駝峯命名mybatis.configuration.map-underscore-to-camel-case=true#設置超時時間-可自行調整sms.default.connect.timeout=sun.net.client.defaultConnectTimeoutsms.default.read.timeout=sun.net.client.defaultReadTimeoutsms.timeout=10000#初始化ascClient須要的幾個參數#短信API產品名稱(短信產品名固定,無需修改)sms.product=Dysmsapi#短信API產品域名(接口地址固定,無需修改)sms.domain=dysmsapi.aliyuncs.com#替換成你的AK (產品密)#你的accessKeyId,填你本身的 上文配置所得 自行配置sms.access.key.id=xxxxxxx#你的accessKeyId,填你本身的 上文配置所得 自行配置sms.access.key.secret=xxxxxxxxx#阿里雲配置你本身的短信模板填入sms.template.code=xxxxxxxx提示:以上是xxxxxxxxx的代碼都得修改爲你本身對應的參數

MessageUtils.java

package com.example.demo.utils;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.http.MethodType;import com.aliyuncs.profile.DefaultProfile;import com.aliyuncs.profile.IClientProfile;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Component;import org.springframework.web.client.RestTemplate;import java.util.HashMap;import java.util.Map;
@Componentpublic class MessageUtils { @Autowired RestTemplate restTemplate;
@Value("${sms.default.connect.timeout}") private String DEFAULT_CONNECT_TIMEOUT;
@Value("${sms.default.read.timeout}") private String DEFAULT_READ_TIMEOUT;
@Value("${sms.timeout}") private String SMS_TIMEOUT;
@Value("${sms.product}") private String SMS_PRODUCT;
@Value("${sms.domain}") private String SMS_DOMAIN;
@Value("${sms.access.key.id}") private String SMS_ACCESSKEYID;
@Value("${sms.access.key.secret}") private String SMS_ACCESSKEYSECRET;
@Value("${sms.template.code}") private String TEMPLATE_CODE;
private static String code;//code對應你短信目標裏面的參數
public Map getPhoneMsg(String phone) { if (phone == null || phone == "") { System.out.println("手機號爲空"); return null; } // 設置超時時間-可自行調整 System.setProperty(DEFAULT_CONNECT_TIMEOUT, SMS_TIMEOUT); System.setProperty(DEFAULT_READ_TIMEOUT, SMS_TIMEOUT); // 初始化ascClient須要的幾個參數 final String product = SMS_PRODUCT; final String domain = SMS_DOMAIN; // 替換成你的AK final String accessKeyId = SMS_ACCESSKEYID; final String accessKeySecret = SMS_ACCESSKEYSECRET; // 初始化ascClient,暫時不支持多region IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
Map map = new HashMap(); try { DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
//獲取驗證碼 code = vcode(); IAcsClient acsClient = new DefaultAcsClient(profile); // 組裝請求對象 SendSmsRequest request = new SendSmsRequest(); // 使用post提交 request.setMethod(MethodType.POST); // 必填:待發送手機號。支持以逗號分隔的形式進行批量調用,批量上限爲1000個手機號碼,批量調用相對於單條調用及時性稍有延遲,驗證碼類型的短信推薦使用單條調用的方式 request.setPhoneNumbers(phone); // 必填:短信簽名-可在短信控制檯中找到 request.setSignName("java學習"); // 必填:短信模板-可在短信控制檯中找到 request.setTemplateCode(TEMPLATE_CODE); // 可選:模板中的變量替換JSON串,如模板內容爲"親愛的${name},您的驗證碼爲${code}"時,此處的值爲 // 友情提示:若是JSON中須要帶換行符,請參照標準的JSON協議對換行符的要求,好比短信內容中包含\r\n的狀況在JSON中須要表示成\\r\\n,不然會致使JSON在服務端解析失敗 request.setTemplateParam("{ \"code\":\"" + code + "\"}"); // 可選-上行短信擴展碼(無特殊需求用戶請忽略此字段) // request.setSmsUpExtendCode("90997"); // 可選:outId爲提供給業務方擴展字段,最終在短信回執消息中將此值帶回給調用者 request.setOutId("yourOutId"); // 請求失敗這裏會拋ClientException異常 SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); map.put("status", sendSmsResponse.getCode()); if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) { // 請求成功 map.put("msg", code); } else { //若是驗證碼出錯,會輸出錯誤碼告訴你具體緣由 map.put("msg", sendSmsResponse.getMessage()); } } catch (Exception e) { e.printStackTrace(); map.put("status", "FAIL"); map.put("msg", "獲取短信驗證碼失敗"); } return map;    } /** * 生成6位隨機數驗證碼 * * @return */ public static String vcode() { String vcode = ""; for (int i = 0; i < 6; i++) { vcode = vcode + (int) (Math.random() * 9); } return vcode;    }}

MessageController.java

package com.example.demo.controller;import com.alibaba.fastjson.JSON;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;import com.example.demo.service.MessageService;import com.example.demo.utils.MessageUtils;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.Map;
@Api(description = "短信接口")@RequestMapping("/smsLogin")@RestControllerpublic class MessageController { @Autowired public MessageService messageService;
@Autowired public MessageUtils messageUtils;
@ApiOperation(value = "獲取短信驗證碼接口", notes = "獲取短信驗證碼接口") @GetMapping("/sendMessage") public Map<String, Object> getSMSMessage(String phone) { Map<String, Object> map = new HashMap<>(); if (phone == null || phone == "") { map.put("code", "FAIL"); map.put("msg", "手機號爲空"); return map; } Map smsMap = messageUtils.getPhoneMsg(phone); if("OK".equals(smsMap.get("status"))){ Map data = messageService.selectSMSDataByPhone(phone); map.put("phone", phone); map.put("smsCode", smsMap.get("msg")); // 將驗證碼存入數據庫 也能夠考慮用redis等方式 這裏就用數據庫作例子 if (data != null) { messageService.updateSMSDataByPhone(map); } else { messageService.insert(map); } smsMap.put("msg", "成功"); } return smsMap; }
@ApiOperation(value = "短信校驗登陸接口", notes = "短信校驗登陸接口") @GetMapping("/login") public Map<String, Object> login(String phone, String smsCode) { Map<String, Object> map = new HashMap<>(); if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(smsCode)) { map.put("code", "FAIL"); map.put("msg", "請檢查數據"); return map; } // 取出對應的驗證碼進行比較便可 Map smsMap = messageService.selectSMSDataByPhone(phone); if (smsMap == null) { map.put("code", "FAIL"); map.put("msg", "該手機號未發送驗證碼"); return map; } String code = (String) smsMap.get("sms_code"); if (!smsCode.equals(code)) { map.put("code", "FAIL"); map.put("msg", "驗證碼不正確"); return map; } map.put("code", "OK"); map.put("msg", "success"); return map; }}

MessageMapper.java

package com.example.demo.mapper;import org.apache.ibatis.annotations.Insert;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Select;import org.apache.ibatis.annotations.Update;import java.util.Map;
@Mapperpublic interface MessageMapper { @Select("select * from SMS_MESSAGE where PHONE=#{phone}") Map selectSMSDataByPhone(String phone);
@Update("update SMS_MESSAGE set SMS_CODE = #{smsCode} where phone=#{phone}") int updateSMSDataByPhone(Map smsMap);
@Insert("insert into SMS_MESSAGE (PHONE,SMS_CODE) values (#{phone},#{smsCode})") int insert(Map smsMap);}

MessageService.java

package com.example.demo.service;import com.example.demo.mapper.MessageMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;
import java.util.Map;
@Servicepublic class MessageService { @Autowired public MessageMapper messageMapper;
public Map selectSMSDataByPhone(String phone) { return messageMapper.selectSMSDataByPhone(phone); }
public int updateSMSDataByPhone(Map smsMap) { return messageMapper.updateSMSDataByPhone(smsMap); }
public int insert(Map smsMap) { return messageMapper.insert(smsMap); }}

index.js

import { MailTwoTone, MobileTwoTone } from '@ant-design/icons';import { Alert, message } from 'antd';import React, { useState } from 'react';import ProForm, { ProFormCaptcha, ProFormText } from '@ant-design/pro-form';
import { getFakeCaptcha, phoneLogin } from '@/service/login';
import styles from './index.less';
export default function({ history }) { const [loading, setLoading] = useState(false);
const handleSubmit = async values => { setLoading(true); let params = { phone: values.mobile, smsCode: values.captcha, };
const result = await phoneLogin(params); if (result.code === 'OK') { message.success(result.msg);
history.push('/home'); } else { message.error(result.msg); } }; return ( <div className={styles.main}> <ProForm initialValues={{ autoLogin: true, }} submitter={{ render: (_, dom) => dom.pop(), submitButtonProps: { loading: loading, size: 'large', style: { width: '100%', }, }, }} onFinish={async values => { handleSubmit(values); }} > <div> <ProFormText fieldProps={{ size: 'large', prefix: <MobileTwoTone className={styles.prefixIcon} />, }} name="mobile" placeholder="手機號" rules={[ { required: true, message: '請輸入手機號!', }, { pattern: /^1\d{10}$/, message: '手機號格式錯誤!', }, ]} /> <ProFormCaptcha fieldProps={{ size: 'large', prefix: <MailTwoTone className={styles.prefixIcon} />, }} captchaProps={{ size: 'large', }} placeholder="請輸入驗證碼" captchaTextRender={(timing, count) => (timing ? `${count} 獲取驗證碼` : '獲取驗證碼')} name="captcha" rules={[ { required: true, message: '請輸入驗證碼!', }, ]} onGetCaptcha={async mobile => { console.log(mobile, 'phone'); const result = await getFakeCaptcha(mobile);
message.success('獲取驗證碼成功!請查看手機'); }} /> </div> </ProForm> </div> );}

login.js

import request from '@/utils/request';
export async function phoneLogin({ phone, smsCode }) { return request(`http://xxxxx:8002/smsLogin/login?phone=${phone}&smsCode=${smsCode}`);}
export async function getFakeCaptcha(mobile) { return request(`http://xxxxx:8002/smsLogin/sendMessage?phone=${mobile}`);}

test.sql

CREATE TABLE `SMS_MESSAGE` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `phone` varchar(11) NOT NULL, `sms_code` varchar(6) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;--每次生成的驗證碼都會存進數據庫,登陸的時候進行查詢判斷

--完--

推薦案例

溫暖提示

爲了方便你們更好的學習,本公衆號常常分享一些 完整的單個功能案例代碼給你們去練習, 若是本公衆號沒有你要學習的功能案例,你能夠聯繫小編(微信:xxf960513)提供你的小需求給我,我安排咱們這邊的開發團隊免費幫你完成你的案例。
注意:只能提單個功能的需求不能要求功能太多,好比要求用什麼技術,有幾個頁面,頁面要求怎麼樣?


請長按識別二維碼

想學習更多的java功能案例請關注

Java項目開發

若是你以爲這個案例以及咱們的分享思路不錯,對你有幫助,請分享給身邊更多須要學習的朋友。別忘了《留言+點在看》給做者一個鼓勵哦!

本文分享自微信公衆號 - web項目開發(javawebkaifa)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索