Jelajahi Sumber

短信登录,短信确认等

薛晓波 6 tahun lalu
induk
melakukan
f5992fe89c

+ 2 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/constants/VerifyConstants.java

@@ -9,4 +9,6 @@ public class VerifyConstants {
     public static final long TIME_OUT = 1000 * 60 * 5;
     public static final String SMS_VERI_TEMPLATE_ID = "73686";
     // public static final String SMS_VERI_TIMEOUT = "30";
+    public static final long MOBILE_VERIFICATION_INTERVAL = 90 * 1000;
+
 }

+ 2 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/service/MailService.java

@@ -16,4 +16,6 @@ public interface MailService {
                          String subject, String content) throws MessagingException;
 
     void sendVerifyEmail(String sender, String receiver, String code) throws MessagingException;
+
+    void sendArrearsEmail();
 }

+ 44 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/service/impl/MailServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.iselab.mooctest.user.service.impl;
 
+import cn.iselab.mooctest.user.configure.MailProperties;
 import cn.iselab.mooctest.user.constants.VerifyConstants;
 import cn.iselab.mooctest.user.service.MailService;
 import org.slf4j.Logger;
@@ -15,6 +16,7 @@ import org.thymeleaf.context.Context;
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
 
 /**
  * @Description: 作用描述
@@ -32,6 +34,23 @@ public class MailServiceImpl implements MailService {
     @Autowired
     TemplateEngine templateEngine;
 
+    @Autowired
+    MailProperties mailProperties;
+
+    private static ArrayList<String> adminEmails = new ArrayList<>();
+
+    // static {
+    //     adminEmails.add("zychen@nju.edu.cn");
+    //     adminEmails.add("chrong.fang@gmail.com");
+    //     adminEmails.add("xujianfeng@mooctest.com");
+    //     adminEmails.add("huangyong@mooctest.com");
+    // }
+    static {
+        adminEmails.add("171256175@qq.com");
+        adminEmails.add("xuexiaobo.dlmu@gmail.com");
+    }
+
+
     @Override
     public void sendNormalEmail(String sender, String receiver, String subject, String content) {
         SimpleMailMessage message = new SimpleMailMessage();
@@ -60,6 +79,7 @@ public class MailServiceImpl implements MailService {
     }
 
 
+
     @Override
     public void sendVerifyEmail(String sender, String receiver, String code) throws MessagingException {
         Context context = new Context();
@@ -67,4 +87,28 @@ public class MailServiceImpl implements MailService {
         String emailContent = templateEngine.process("email/verify_mail", context);
         sendHtmlEmail(sender,receiver, "【验证码-慕测科技】", emailContent);
     }
+
+    @Override
+    public void sendArrearsEmail() {
+        Context context = new Context();
+        context.setVariable("message", "平台所使用的短信服务可能已欠费,请尽快前往充值");
+        context.setVariable("rechargeUrl", "http://www.yuntongxun.com/");
+        String emailContent = templateEngine.process("email/arrears_mail", context);
+        MimeMessage message = mailSender.createMimeMessage();
+        String[] receivers = adminEmails.toArray(new String[adminEmails.size()]);
+
+        try {
+            MimeMessageHelper helper = new MimeMessageHelper(message,true);
+            helper.setFrom(mailProperties.getUsername(), VerifyConstants.SENDER_NAME);
+            helper.setTo(receivers);
+            helper.setSubject("【MOOCTEST】短信服务欠费通知");
+            helper.setText(emailContent, true);
+        } catch (UnsupportedEncodingException e) {
+            logger.error("设置发件人名称时编码出错", e);
+        } catch (MessagingException e){
+            logger.error("设置发件人信息出错", e);
+        }
+
+        mailSender.send(message);
+    }
 }

+ 14 - 5
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/util/MSUtil.java

@@ -6,6 +6,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @Author: xuexb
@@ -22,8 +24,8 @@ public class MSUtil {
     public static String sendSmsVerification(String receiver, String veriCode) {
 
         // send short message by invoking SDK
-        HashMap<String, Object> result = sendSMSSDK(receiver, VerifyConstants.SMS_VERI_TEMPLATE_ID, veriCode, "10");
-
+        // HashMap<String, Object> result = sendSMSSDK(receiver, VerifyConstants.SMS_VERI_TEMPLATE_ID, veriCode, "5分钟");
+        HashMap<String, Object> result = sendSMSSDK(receiver, "1", veriCode, "5");
         // Check return result to see if process success
         if ("000000".equals(result.get("statusCode"))) {
             // success
@@ -53,12 +55,12 @@ public class MSUtil {
         // Initialize ACCOUNT SID & AUTH TOKEN
         // * Can be found by viewing developer's account in `Console` on
         // * website(http://www.yuntongxun.com)
-        restAPI.setAccount("aaf98f89521b91a301522abe22af1760", "356fff5595a14e32a2bc2856cc0f0f5a");
-
+        // restAPI.setAccount("aaf98f89521b91a301522abe22af1760", "356fff5595a14e32a2bc2856cc0f0f5a");
+        restAPI.setAccount("8a216da867e881cb0167f4125c6a06f5", "08465874ee6645f083f2228ec725ec9d");
         // Initialize Target
         // * Can be found in Console:
         // * "Application - application list - specific app"
-        restAPI.setAppId("8a48b551522ff931015234f9a0c10e53");
+        restAPI.setAppId("8a216da867e881cb0167f4125cbe06fb");
 
         // Send SMS
         // * @Parameters
@@ -80,4 +82,11 @@ public class MSUtil {
         int veriCode = (int) Math.round(100000 + Math.random() * 899999);
         return String.valueOf(veriCode);
     }
+
+    public static boolean isMobileNO(String mobiles) {
+        Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9])|(14[5,7])| (17[0,1,3,5-8]))\\d{8}$");
+        Matcher m = p.matcher(mobiles);
+        return m.matches();
+    }
+
 }

+ 22 - 4
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/PageController.java

@@ -35,11 +35,11 @@ public class PageController extends BaseController{
             if(!callback.getRedirectURL().startsWith("http"))
                 callback.setRedirectURL("http://"+callback);
             afterLogin = callback.getRedirectURL();
-        }else if(callback.getDefaultURL()!=null)
+        }else if (request.getSession().getAttribute("RedirectURL")!=null){
+            afterLogin = (String) request.getSession().getAttribute("RedirectURL");
+        }
+        else if(callback.getDefaultURL()!=null)
             afterLogin = callback.getDefaultURL();
-        else
-            afterLogin = UrlConstants.DFAULT_GOTO;
-
         LOG.info("RedirectURL---" + afterLogin);
         HttpSession session = request.getSession();
         session.setAttribute("redirectURL", afterLogin);
@@ -70,6 +70,24 @@ public class PageController extends BaseController{
         }
     }
 
+    @RequestMapping(value = UrlConstants.PAGE + "mobile/login", method = RequestMethod.GET)
+    public String mobileLogin(){
+        return "mobile_login";
+    }
+
+    @RequestMapping(value = UrlConstants.PAGE + "mobile/dologin", method = RequestMethod.POST)
+    public String checkMobileLogin(Model model, UserVO userVO, HttpServletRequest request){
+        ResponseResult<UserDTO> result = userLogic.loginByMobile(userVO);
+        model.addAttribute("result", result);
+        if (result.getStatus() != ResponseStatus.SUCCESS){
+            return "mobile_login";
+        }
+        request.getSession().setAttribute("UserId", ((UserDTO)result.getData()).getId());
+        String redirectURL = (String) request.getSession().getAttribute("redirectURL");
+        redirectURL = redirectURL==null?UrlConstants.DFAULT_GOTO:redirectURL;
+        return "redirect:"+redirectURL;
+    }
+
     @RequestMapping(value = UrlConstants.PAGE + "register", method = RequestMethod.GET)
     public String register(){
         return "register";

+ 10 - 2
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/TestController.java

@@ -8,6 +8,7 @@ import cn.iselab.mooctest.user.model.VerifyCode;
 import cn.iselab.mooctest.user.service.MailService;
 import cn.iselab.mooctest.user.service.VerifyCodeService;
 import cn.iselab.mooctest.user.util.MSUtil;
+import cn.iselab.mooctest.user.web.logic.UserLogic;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
@@ -34,6 +35,9 @@ public class TestController extends BaseController{
     @Autowired
     VerifyCodeService verifyCodeService;
 
+    @Autowired
+    UserLogic userLogic;
+
     @RequestMapping(value = "/test/first", method = RequestMethod.GET)
     public Map<String, Object> firstResp(HttpServletRequest request){
         Map<String, Object> map = new HashMap<>();
@@ -105,9 +109,13 @@ public class TestController extends BaseController{
     }
 
     @RequestMapping(value = "/test/mobilecode", method = RequestMethod.GET)
-    public void mobileCode(){
-        MSUtil.sendSmsVerification("18013976047", "123456");
+    public ResponseResult<String> mobileCode(UserDTO userDTO){
+        return userLogic.sendMobileVerfication(userDTO);
     }
 
+    @RequestMapping(value = "/test/emails", method = RequestMethod.GET)
+    public void mails(){
+            mailService.sendArrearsEmail();
+    }
 
 }

+ 13 - 1
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/UserController.java

@@ -5,8 +5,10 @@ import cn.iselab.mooctest.user.constants.ResponseStatus;
 import cn.iselab.mooctest.user.constants.UrlConstants;
 import cn.iselab.mooctest.user.data.ResponseResult;
 import cn.iselab.mooctest.user.util.EncryptionUtil;
+import cn.iselab.mooctest.user.web.data.UserVO;
 import cn.iselab.mooctest.user.web.logic.UserLogic;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
@@ -46,7 +48,7 @@ public class UserController extends BaseController {
     }
 
 
-    @RequestMapping(value = UrlConstants.API + "dologin", method = RequestMethod.POST)
+    @RequestMapping(value = UrlConstants.API + "login", method = RequestMethod.POST)
     public ResponseResult<UserDTO> checkLogin(@RequestBody UserDTO user, HttpServletRequest request, HttpServletResponse response){
         // System.out.println("password"+user.getPassword());
         String password = EncryptionUtil.encryptMD5(user.getPassword());
@@ -75,6 +77,11 @@ public class UserController extends BaseController {
         return result;
     }
 
+    @RequestMapping(value = UrlConstants.API + "mobile/login", method = RequestMethod.GET)
+    public ResponseResult<Object> mobileLogin(UserVO userVO, HttpServletRequest request){
+        return null;
+    }
+
     @RequestMapping(value = UrlConstants.API + "verify/mail", method = RequestMethod.POST)
     public ResponseResult<String> sendVerifyEmail(UserDTO userDTO){
         ResponseResult<String> result = new ResponseResult<>();
@@ -82,5 +89,10 @@ public class UserController extends BaseController {
         return result;
     }
 
+    @RequestMapping(value = UrlConstants.API + "verify/mobile", method = RequestMethod.POST)
+    public ResponseResult<String> sendVerifyMobileMessage(UserDTO userDTO){
+        return userLogic.sendMobileVerfication(userDTO);
+    }
+
 
 }

+ 4 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/logic/UserLogic.java

@@ -41,6 +41,10 @@ public interface UserLogic {
 
     ResponseResult<String> sendVerifyEmail(UserDTO userDTO);
 
+    ResponseResult<String> sendMobileVerfication(UserDTO userDTO);
+
+    ResponseResult<UserDTO> loginByMobile(UserVO userVO);
+
 
 
 

+ 77 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/logic/impl/UserLogicImpl.java

@@ -333,4 +333,81 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
         LOG.info(result.getMsg()+"-Email: " + receiver + "-code: "+ verifyCode.getCode());
         return result;
     }
+
+    @Override
+    public ResponseResult<String> sendMobileVerfication(UserDTO userDTO) {
+        String receiver = userDTO.getMobile();
+        ResponseResult<String> result = new ResponseResult<>();
+        if (receiver == null || !MSUtil.isMobileNO(receiver)){
+            result.init(ResponseStatus.FAILED, "手机号不合法!", receiver);
+            LOG.error(result.getMsg() + " mobile: " + receiver);
+            return result;
+        }
+        VerifyCode latestVerifyCode = verifyCodeService.getLatestVerifyCode("mobile", receiver);
+        if (latestVerifyCode != null ) {
+            long waitTime = (latestVerifyCode.getCreateTime().getTime()
+                    + VerifyConstants.MOBILE_VERIFICATION_INTERVAL)
+                    - System.currentTimeMillis();
+            if(waitTime > 0){
+                result.init(ResponseStatus.FAILED, "发送过于频繁," + waitTime/1000 + "秒后重试", receiver);
+                LOG.error(result.getMsg() + "-receiver: " + receiver);
+                return result;
+            }
+        }
+
+        String code = MSUtil.generateRandomVeriCode();
+        String successCode = "000000";
+        String arrearsCode = "121002";
+        String sendResult = MSUtil.sendSmsVerification(receiver, code);
+        if(sendResult.equals(successCode)){
+            VerifyCode verifyCode = new VerifyCode();
+            verifyCode.setType("mobile");
+            verifyCode.setReceiver(receiver);
+            verifyCode.setCode(code);
+            verifyCode.setCreateTime(new Timestamp(System.currentTimeMillis()));
+            verifyCode.setExpiredTime(new Timestamp(System.currentTimeMillis()
+                    + VerifyConstants.TIME_OUT));
+            verifyCodeService.saveVerifyCode(verifyCode);
+            result.init(ResponseStatus.SUCCESS, "短信发送成功", receiver);
+            LOG.info(result.getMsg() + ", mobile: " + receiver);
+        }else{
+            if (sendResult.equals(arrearsCode)){
+                mailService.sendArrearsEmail();
+            }
+            result.init(ResponseStatus.FAILED, "短信服务异常", receiver);
+            LOG.error(result.getMsg(), "- mobile: " + receiver);
+        }
+
+        return result;
+
+    }
+
+    @Override
+    public ResponseResult<UserDTO> loginByMobile(UserVO userVO) {
+        ResponseResult<UserDTO> result = new ResponseResult<>();
+        String mobile = userVO.getMobile();
+        String code = userVO.getVerifyCode();
+        if (mobile == null || !MSUtil.isMobileNO(mobile)){
+            result.init(ResponseStatus.FAILED, "手机号不正确", userVO);
+            LOG.error(result.getMsg() + userVO.getMobile());
+            return result;
+        }
+        if(!verifyCodeService.validateVerifyCode("mobile", mobile, code)){
+            result.init(ResponseStatus.FAILED, "手机号或验证码不正确", userVO);
+            LOG.error(result.getMsg() + " - mobile: "+mobile + " - code: " + code);
+            return result;
+        }
+        User user = userService.findByMobile(mobile);
+        if (user == null){
+            result.init(ResponseStatus.FAILED, "该手机号未绑定慕测账号", userVO);
+            LOG.error(result.getMsg() + userVO.getMobile());
+            return result;
+        }
+        UserDTO userDTO = userWrapper.wrap(user);
+        result.init(ResponseStatus.SUCCESS, "手机登录成功", userDTO);
+        LOG.error(result.getMsg() + " - mobile: " + userVO.getMobile());
+        return result;
+    }
+
+
 }

+ 13 - 0
mooctest-user-server/src/main/resources/templates/email/arrears_mail.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>【慕测科技】通知邮件</title>
+</head>
+<body>
+尊敬的管理员:<br>
+您好,这是一封通知邮件,<span th:text="${message}"></span>
+<br>
+<a th:href="${rechargeUrl}">充值连接</a>
+</body>
+</html>

+ 2 - 2
mooctest-user-server/src/main/resources/templates/login.html

@@ -43,14 +43,14 @@
 
                 <div p-t-8 p-b-20>
                     <div class="text-left" style="float: left;">
-                        <a href="##">手机登录</a>
+                        <a href="/page/mobile/login">手机登录</a>
                     </div>
                     <div class="text-right" style="float: right;">
                         <a href="javascript:">忘记密码?</a>
                     </div>
                 </div>
                 <div class="text-center p-t-6 p-b-20">
-                    <span style="color: red" th:unless="${result==null}" th:text="${result.msg}"></span>
+                    <span style="color: red" th:text="${result==null}?'&nbsp;':${result.msg}"></span>
                 </div>
                 <div class="container-login100-form-btn">
                     <div class="wrap-login100-form-btn">

+ 121 - 2
mooctest-user-server/src/main/resources/templates/mobile_login.html

@@ -1,10 +1,129 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
 <head>
     <meta charset="UTF-8">
-    <title></title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+
+    <title>慕测平台</title>
+    <meta name="keywords" content="" />
+    <meta name="description" content="" />
+
+    <link rel="stylesheet" type="text/css" th:href="@{/vendor/bootstrap/css/bootstrap.min.css}">
+    <link rel="stylesheet" type="text/css" th:href="@{/fonts/font-awesome-4.7.0/css/font-awesome.min.css}">
+    <link rel="stylesheet" type="text/css" th:href="@{/fonts/iconic/css/material-design-iconic-font.min.css}">
+    <link rel="stylesheet" type="text/css" th:href="@{/css/util.css}">
+    <link rel="stylesheet" type="text/css" th:href="@{/css/main.css}">
 </head>
+
 <body>
 
+<div class="limiter">
+    <div class="container-login100" th:style="'background-image:url(/images/bg.jpg);'">
+        <div class="wrap-login100 p-l-40 p-r-40 p-t-30 p-b-25">
+            <form th:action="@{/page/mobile/dologin}" method="post" class="login100-form validate-form">
+                <div id="login-logo" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">MOOCTEST</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入 shou'ji'hao">
+                    <span class="label-input100">手机号</span>
+                    <input id="mobile" class="input100" type="text" name="mobile" placeholder="请输入手机号" required="邮箱账号不可为空">
+                    <span class="focus-input100" data-symbol="&#xf206;"></span>
+                </div>
+
+                <div class="wrap-input100 validate-input" data-validate="请输入验证码">
+                    <span class="label-input100">验证码</span>
+                    <input class="input100" type="text" name="verifyCode" placeholder="请输入验证码" required="验证码不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </div>
+
+                <div p-t-8 p-b-20>
+                    <div class="text-left">
+                        <a href="/page/login">账号登录</a>
+                    </div>
+                    <!--<div class="text-right" style="float: right;">-->
+                        <!--<span>&nbsp;&nbsp;</span>-->
+                    <!--</div>-->
+                </div>
+                <div class="text-center p-t-6 p-b-8">
+                    <span id="info" style="color: red" th:text="${result==null}?'&nbsp;':${result.msg}"></span>
+                </div>
+                <div class="container-login100-form-btn" style="width: 50%; float: left;">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="button"  id="sendVerify" class="login100-form-btn" onclick="sendVerifyCode(this)" >获取验证码</button>
+                    </div>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button class="login100-form-btn">登 录</button>
+                    </div>
+                </div>
+
+                <div class="txt1 text-center p-t-15 p-b-5">
+                    <span>第三方登录</span>
+                </div>
+
+                <div class="flex-c-m">
+                    <a href="#" class="login100-social-item bg1">
+                        <i class="fa fa-wechat"></i>
+                    </a>
+
+                    <a href="#" class="login100-social-item bg2">
+                        <i class="fa fa-qq"></i>
+                    </a>
+
+                    <a href="#" class="login100-social-item bg3">
+                        <i class="fa fa-weibo"></i>
+                    </a>
+                </div>
+
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/register" class="txt2">立即注册</a>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+
+<script th:src="@{/vendor/jquery/jquery-3.2.1.min.js}"></script>
+<script th:src="@{/js/main.js}"></script>
+<script type="text/javascript">
+    function sendVerifyCode(obj) {
+        var mobile = $("#mobile").val();
+        if (mobile == null || mobile.trim() == "") {
+            document.getElementById("info").innerText = "手机号不能为空";
+            return;
+        }
+        if (!mobile.match(/^(13[0-9]{9})|(18[0-9]{9})|(14[0-9]{9})|(17[0-9]{9})|(15[0-9]{9})$/)){
+            document.getElementById("info").innerText = "手机号格式不正确,请重新输入";
+            return
+        }
+
+        var data = {"mobile":mobile};
+        $.ajax({
+            url:"/api/verify/mobile",
+            type:"POST",
+            data:data,
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    alert("发送失败, 原因:"+result.msg);
+                    document.getElementById("info").innerText = result.msg;
+                }else{
+                    alert("发送成功,请尽快查收!");
+                    document.getElementById("info").innerHTML = "&nbsp;";
+                    settime(obj);
+                }
+            }
+        })
+    }
+</script>
 </body>
 </html>