Java 手機驗證碼
傳送簡訊驗證碼+登陸功能
置頂 2017年12月14日 19:39:55 Elsa曉冰 閱讀數:5100 標籤: 簡訊驗證碼登陸更多
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/binggetong/article/details/78805992
業務:
手機端點擊發送驗證碼,呼叫第三方平臺(我們用的是“任信了”平臺)的介面,去給手機發簡訊驗證碼。
過程:
程式碼:
-
/**
-
* 傳送簡訊驗證碼
-
* @param json 前臺傳入電話號碼
-
* @return 返回傳送結果向前臺
-
*/
-
@RequestMapping("/getTestCode")
-
@ResponseBody
-
public GetTestCodeResult sendTestCode(@RequestParam(value="phone",defaultValue="") String phoneNumber ){
-
GetTestCodeResult result = new GetTestCodeResult();
-
if(phoneNumber == null || phoneNumber.length()==0 ){
-
result.setState(Result.ERROR);
-
result.setMessage("手機號為空");
-
return result;
-
}
-
String code =TestCode.getCode();
-
if( code== null || code.length()==0){
-
result.setState(Result.ERROR);
-
result.setMessage("無效的驗證碼");
-
return result;
-
}
-
try {
-
SMS.batchsendsm(phoneNumber,code);
-
} catch (Exception e) {
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼傳送失敗");
-
return result;
-
}
-
TestCodeInforVo testCodeInfor = new TestCodeInforVo();
-
testCodeInfor.setCode(code);
-
testCodeInfor.setPhone(phoneNumber);
-
testCodeInfor.setDate(System.currentTimeMillis());
-
testCodeInforMap.put(phoneNumber,testCodeInfor);
-
result.setState(Result.SUCCESS);
-
result.setMessage("驗證碼傳送成功");
-
result.setData(code); //測試
-
return result;
-
}
上面這個是傳送驗證碼的方法,其中包括了2個工具類:
No.1 生成5位隨機數
-
public class TestCode {
-
private final static int codeLength =5;
-
/**
-
* @see 產生隨機驗證碼
-
* @return 驗證碼字串
-
*/
-
public static String getCode(){
-
Random rand = new Random();
-
int a ;
-
String result ="";
-
for( int j =0; j<codeLength; j++ ){
-
a = Math.abs( rand.nextInt()%9 );
-
result += String.valueOf(a);
-
}
-
return result;
-
}
-
}
No.2 呼叫第三方傳送簡訊介面
-
package com.cn.zhongcai.util.app.util;
-
import java.io.BufferedReader;
-
import java.io.IOException;
-
import java.io.InputStreamReader;
-
import java.io.OutputStreamWriter;
-
import java.net.HttpURLConnection;
-
import java.net.URL;
-
import java.net.URLEncoder;
-
import java.security.MessageDigest;
-
import java.security.NoSuchAlgorithmException;
-
public class SMS {
-
//把介面地址和引數賦值,之後呼叫SMS3方法,引數photo是手機號,code是之前生成的驗證碼。
-
public static void batchsendsm(String phone,String code)
-
{
-
try{
-
String userid = URLEncoder.encode("15732622061","UTF-8"); //188
-
String url = "http://apis.renxinl.com:8080/smsgate/varsend.do?";
-
String para = "user="+userid+"&pwd=9fa41ab9c5352bc29babd621a73d¶ms="+phone+","+code+"&mid=15552";
-
String str="";
-
str=SMS3(para,url);
-
System.out.println(str);
-
}catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
//postData是上面拼接的引數值,postURL 是介面的地址。我覺得這個方法是能訪問到第三方介面的方法。
-
public static String SMS3(String postData,String postUrl){
-
try{
-
URL url = new URL(postUrl);
-
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-
conn.setRequestMethod("POST");
-
conn.setRequestProperty("accept", "*/*");
-
conn.setRequestProperty("connection", "Keep-Alive");
-
conn.setRequestProperty("user-agent",
-
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
-
conn.setUseCaches(false);
-
conn.setDoOutput(true);
-
conn.setDoInput(true);
-
OutputStreamWriter out= new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
-
out.write(postData);
-
out.flush();
-
out.close();
-
if(conn.getResponseCode()!=HttpURLConnection.HTTP_OK){
-
System.out.println("connect failed!");
-
return "";
-
}
-
String line,result = "";
-
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
-
while((line= in.readLine()) != null){
-
result += line+"\n";
-
}
-
in.close();
-
return result;
-
}catch(IOException e){
-
e.printStackTrace(System.out);
-
}
-
return "";
-
}
-
}
其中:
1、我從第三方那要了一個demo,從中摘出來自己需要用的程式碼。
2、簡訊介面有固定模板和變數模板, 這裡我們用到的是變數模板,因為驗證碼是個變數。
3、介面文件裡給的很清楚:
4、其中最後一步儲存,該手機號的驗證碼和傳送時間,用到了一個Map儲存。
private final static Map<String, TestCodeInforVo> testCodeInforMap = new HashMap<String,TestCodeInforVo>();
傳送完驗證碼之後:
testCodeInforMap.put(phoneNumber,testCodeInfor);
儲存到了map裡面,到時候找驗證碼和時間,也從這個map裡面找,手機號是key,這個儲存著驗證碼和時間的實體是value。
簡訊驗證碼就到此告一段落。接下來看登陸的邏輯:
登陸的過程:
登陸程式碼:
-
/**
-
* 使用者登入介面
-
* @param json 登入引數
-
* @return 登入成功返回使用者資訊
-
*/
-
@RequestMapping("/login")
-
@ResponseBody
-
public LoginResult login(@RequestParam(value="testCode",defaultValue="") String testCode,
-
@RequestParam(value="identity",defaultValue="") String identity,
-
@RequestParam(value="phone",defaultValue="") String phone, HttpServletRequest request){
-
//String serverPath = request.getScheme() + "://"+ request.getServerName() + ":" +
-
// request.getServerPort()+request.getContextPath() + "/";
-
LoginResult result = new LoginResult();
-
if( identity == null || identity.length() == 0 ){
-
result.setState(Result.ERROR);
-
result.setMessage("證件號為空");
-
return result;
-
}
-
if(phone== null || phone.length() == 0 ){
-
result.setState(Result.ERROR);
-
result.setMessage("手機號為空");
-
return result;
-
}
-
if( testCode == null || testCode.length() == 0 ){
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼為空");
-
return result;
-
}
-
TestCodeInforVo testCodeInfor = (TestCodeInforVo) testCodeInforMap.get(phone);
-
if( testCodeInfor == null || testCodeInfor.getCode() == null || testCodeInfor.getCode().length()==0 ){
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼不存在");
-
return result;
-
}
-
if(!testCode.equals(testCodeInfor.getCode())){
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼錯誤");
-
return result;
-
}
-
testCodeInforMap.remove(phone);
-
//驗證驗證碼是否過期
-
if( System.currentTimeMillis()- testCodeInfor.getDate() > testCodeOutDate ){
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼已過期");
-
return result;
-
}
-
List<UserEntity> users = userService.getUserByPhoneIdentity(phone,identity);
-
if( users.isEmpty()){
-
result.setState(Result.ERROR);
-
result.setMessage("使用者不存在");
-
return result;
-
}
-
if( users.size() != 1){
-
result.setState(Result.ERROR);
-
result.setMessage("認證使用者不唯一");
-
return result;
-
}
-
if( users.get(0).getAccountStatus() != null && users.get(0).getAccountStatus().equals("0")){
-
result.setState(Result.ERROR);
-
result.setMessage("該使用者被凍結");
-
return result;
-
}
-
UserEntity user = users.get(0);
-
user.setQrCode(user.getQrCode());
-
user.setPersonalPhotos(user.getPersonalPhotos());
-
user.setIdCardAvatarFace(user.getIdCardAvatarFace());
-
user.setIdCardNationalEmblem(user.getIdCardNationalEmblem());
-
String siteID="";
-
//根據user的role去判斷該使用者所在的站點ID
-
if (user.getRole()==0) {
-
//0是管理員
-
//根據使用者的ID去站點表裡查詢站點的最早新增的哪一個站點Id
-
siteID=userService.findSiteIDByTimeAdmin(user.getId());
-
}
-
if(user.getRole()==2)//2是業主
-
{
-
//根據使用者的ID去站點表裡查詢站點的最早新增的哪一個站點Id
-
siteID=userService.findSiteIDByTimeOwner(user.getId());
-
}
-
if (user.getRole()==1) {//1是營業員
-
//營業員對應的,最早新增的哪一個站點Id
-
siteID=userService.findSiteIDByTimeOwnerSale(user.getId());
-
}
-
user.setSiteID(siteID);
-
result.setState(Result.SUCCESS);
-
result.setMessage("登入成功");
-
AppLoginUser appUser=new AppLoginUser();
-
HttpSession session=request.getSession();
-
appUser.setUserID(user.getId());
-
appUser.setUserName(user.getName());
-
appUser.setUserNum(user.getUserNumber());
-
OrgStructure org=orgService.getOrgByAccount(user.getName());
-
//appUser.setOrgId(org.getOrgId());
-
session.setAttribute("appLoginUser", appUser);
-
result.setData(user);
-
return result;
-
}
其中:
1、判斷驗證碼是否正確:(從剛才那個map裡面,根據手機號取值)
TestCodeInforVo testCodeInfor = (TestCodeInforVo) testCodeInforMap.get(phone);
從這個實體裡面取出驗證碼和時間。
2、驗證碼是否過期:
過期時間:
private final static long testCodeOutDate = 5*60*1000; //驗證碼過期時間
-
//驗證驗證碼是否過期
-
if( System.currentTimeMillis()- testCodeInfor.getDate() > testCodeOutDate ){
-
result.setState(Result.ERROR);
-
result.setMessage("驗證碼已過期");
-
return result;
-
}
驗證完之後刪除他:
testCodeInforMap.remove(phone);
3、當初想的是存到session裡面會怎麼寫,還沒想好,希望路過的大神指導。
小結:
傳送驗證碼和登陸的邏輯之前覺得挺複雜的,當畫圖總結一遍之後,思路就清楚多了,還是要靜下心來多總結。