Преглед изворни кода

修改邮箱,修改手机号

xuexb пре 6 година
родитељ
комит
46851da3ac
18 измењених фајлова са 1183 додато и 32 уклоњено
  1. 2 0
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/service/VerifyCodeService.java
  2. 113 0
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/util/EncryptionUtil.java
  3. 50 7
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/PageController.java
  4. 12 3
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/TestController.java
  5. 20 1
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/UserController.java
  6. 2 0
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/data/UserVO.java
  7. 55 0
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/data/UserVOWrapper.java
  8. 9 0
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/logic/UserLogic.java
  9. 211 7
      mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/logic/impl/UserLogicImpl.java
  10. 2 2
      mooctest-user-server/src/main/resources/templates/forget_password.html
  11. 108 0
      mooctest-user-server/src/main/resources/templates/forget_password_email.html
  12. 107 0
      mooctest-user-server/src/main/resources/templates/forget_password_mobile.html
  13. 111 0
      mooctest-user-server/src/main/resources/templates/forget_password_reset.html
  14. 1 1
      mooctest-user-server/src/main/resources/templates/login.html
  15. 137 0
      mooctest-user-server/src/main/resources/templates/reset_email.html
  16. 138 0
      mooctest-user-server/src/main/resources/templates/reset_mobile.html
  17. 105 0
      mooctest-user-server/src/main/resources/templates/reset_password.html
  18. 0 11
      mooctest-user-server/src/main/resources/templates/test_success.html

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

@@ -1,5 +1,6 @@
 package cn.iselab.mooctest.user.service;
 
+import cn.iselab.mooctest.user.data.ResponseResult;
 import cn.iselab.mooctest.user.model.VerifyCode;
 
 /**
@@ -13,4 +14,5 @@ public interface VerifyCodeService {
     VerifyCode saveVerifyCode(VerifyCode verifyCode);
 
     boolean validateVerifyCode(String type, String receiver, String code);
+
 }

+ 113 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/util/EncryptionUtil.java

@@ -2,14 +2,28 @@ package cn.iselab.mooctest.user.util;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
 
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import java.io.IOException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 
 public class EncryptionUtil {
 
     private static final Logger LOG = LoggerFactory.getLogger(EncryptionUtil.class);
 
+
+    // 定义 加密算法,可用 DES,DESede,Blowfish
+    private static String Algorithm = "DES";
+    private static String defaultKey = "witest.net";
+
+
     public static String encryptMD5(String str) {
         String s = str;
         if (s == null) {
@@ -30,4 +44,103 @@ public class EncryptionUtil {
             return value;
         }
     }
+
+    public static String encryptDES(String content) throws Exception {
+        return encryptDES(content, defaultKey);
+    }
+
+    public static String decryptDES(String content) throws Exception {
+        return decryptDES(content, defaultKey);
+    }
+
+
+    /**
+     * Description 根据键值进行加密
+     *
+     * @param data
+     * @param key  加密键byte数组
+     * @return
+     * @throws Exception
+     */
+    public static String encryptDES(String data, String key) throws Exception {
+        byte[] bt = encryptDES(data.getBytes(), key.getBytes());
+        String strs = new BASE64Encoder().encode(bt);
+        return strs;
+    }
+
+    /**
+     * Description 根据键值进行解密
+     *
+     * @param data
+     * @param key  加密键byte数组
+     * @return
+     * @throws IOException
+     * @throws Exception
+     */
+    public static String decryptDES(String data, String key) throws IOException,
+            Exception {
+        if (data == null)
+            return null;
+        BASE64Decoder decoder = new BASE64Decoder();
+        byte[] buf = decoder.decodeBuffer(data);
+        byte[] bt = decryptDES(buf, key.getBytes());
+        return new String(bt);
+    }
+
+    /**
+     * Description 根据键值进行加密
+     *
+     * @param data
+     * @param key  加密键byte数组
+     * @return
+     * @throws Exception
+     */
+    private static byte[] encryptDES(byte[] data, byte[] key) throws Exception {
+        // 生成一个可信任的随机数源
+        SecureRandom sr = new SecureRandom();
+
+        // 从原始密钥数据创建DESKeySpec对象
+        DESKeySpec dks = new DESKeySpec(key);
+
+        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);
+        SecretKey securekey = keyFactory.generateSecret(dks);
+
+        // Cipher对象实际完成加密操作
+        Cipher cipher = Cipher.getInstance(Algorithm);
+
+        // 用密钥初始化Cipher对象
+        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
+
+        return cipher.doFinal(data);
+    }
+
+
+    /**
+     * Description 根据键值进行解密
+     *
+     * @param data
+     * @param key  加密键byte数组
+     * @return
+     * @throws Exception
+     */
+    private static byte[] decryptDES(byte[] data, byte[] key) throws Exception {
+        // 生成一个可信任的随机数源
+        SecureRandom sr = new SecureRandom();
+
+        // 从原始密钥数据创建DESKeySpec对象
+        DESKeySpec dks = new DESKeySpec(key);
+
+        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(Algorithm);
+        SecretKey securekey = keyFactory.generateSecret(dks);
+
+        // Cipher对象实际完成解密操作
+        Cipher cipher = Cipher.getInstance(Algorithm);
+
+        // 用密钥初始化Cipher对象
+        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
+
+        return cipher.doFinal(data);
+    }
 }

+ 50 - 7
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/PageController.java

@@ -8,11 +8,11 @@ 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 com.sun.org.apache.xpath.internal.operations.Mod;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -30,6 +30,7 @@ public class PageController extends BaseController{
 
     @RequestMapping(value = UrlConstants.PAGE + "login", method = RequestMethod.GET)
     public String login(Callback callback, HttpServletRequest request){
+        System.out.println(System.currentTimeMillis());
         String afterLogin = null;
         if(callback.getRedirectURL()!=null && callback.getRedirectURL().trim().length()>0){
             if(!callback.getRedirectURL().startsWith("http"))
@@ -104,17 +105,59 @@ public class PageController extends BaseController{
         return "success_page";
     }
 
-    @RequestMapping(value = UrlConstants.PAGE + "forgetPassword", method = RequestMethod.GET)
+    @RequestMapping(value = UrlConstants.PAGE + "forgetPassword/mobile", method = RequestMethod.GET)
     public String forgetPassword(){
-        return "forget_password";
+        return "forget_password_mobile";
     }
 
-    @ResponseBody
-    @RequestMapping(value = UrlConstants.PAGE + "forgetPassword/check", method = RequestMethod.POST)
-    public UserVO foregetPasswordCheck(UserVO userVO){
-        return userVO;
+    @RequestMapping(value = UrlConstants.PAGE + "forgetPassword/email", method = RequestMethod.GET)
+    public String forgetPasswordByEmail(){
+        return "forget_password_email";
     }
 
+    @RequestMapping(value = UrlConstants.PAGE + "forgetPassword/check/{type}", method = RequestMethod.POST)
+    public String foregetPasswordCheck(@PathVariable("type") String type, UserVO userVO, Model model){
+        ResponseResult<UserVO> result = userLogic.checkVerifyCode(userVO, type);
+        if (result.getStatus()!=ResponseStatus.SUCCESS){
+            model.addAttribute("result", result);
+            return "forget_password_"+type;
+        }
+        model.addAttribute("user", (UserVO)result.getData());
+        return "forget_password_reset";
+    }
+
+    @RequestMapping(value = UrlConstants.PAGE + "update/password", method = RequestMethod.GET)
+    public String updatePassword(Model model, HttpServletRequest request){
+        if (request.getSession().getAttribute("userId")==null){
+            model.addAttribute("message", "请前往登录后再进行操作");
+            return "error_page";
+        }
+        return "reset_password";
+    }
+
+    @RequestMapping(value = UrlConstants.PAGE + "update/email", method = RequestMethod.GET)
+    public String updateEmail(Model model, HttpServletRequest request){
+        if (request.getSession().getAttribute("userId")==null){
+            model.addAttribute("message", "请前往登录后再进行操作");
+            return "error_page";
+        }
+        return "reset_email";
+    }
+
+    @RequestMapping(value = UrlConstants.PAGE + "update/mobile", method = RequestMethod.GET)
+    public String updateMobile(Model model, HttpServletRequest request){
+        if (request.getSession().getAttribute("userId")==null){
+            model.addAttribute("message", "请前往登录后再进行操作");
+            return "error_page";
+        }
+        return "reset_mobile";
+    }
+
+    @RequestMapping(value = UrlConstants.PAGE + "operation/success", method = RequestMethod.GET)
+    public String operationSuccess(Model model){
+        model.addAttribute("message", "操作成功!");
+        return "success_page";
+    }
 
     @RequestMapping("error-404")
     public String toPage404(Model model){

+ 12 - 3
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/ctrl/TestController.java

@@ -7,17 +7,15 @@ import cn.iselab.mooctest.user.data.ResponseResult;
 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.data.UserVO;
 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.*;
 import org.springframework.web.servlet.ModelAndView;
 
-import javax.annotation.Resource;
 import javax.mail.MessagingException;
 import javax.servlet.http.HttpServletRequest;
-import java.rmi.MarshalledObject;
 import java.sql.Timestamp;
 import java.util.HashMap;
 import java.util.Map;
@@ -123,4 +121,15 @@ public class TestController extends BaseController{
         return new ModelAndView("forget_password");
     }
 
+    @RequestMapping(value = "/test/resetpage", method = RequestMethod.GET)
+    public ModelAndView resetPage(){
+        ModelAndView modelAndView = new ModelAndView();
+        UserVO userVO = new UserVO();
+        userVO.setEmail("171333333@qq.com");
+        userVO.setVerifyCode("sdlkfjlsfksld");
+        modelAndView.setViewName("forget_password_reset");
+        modelAndView.addObject("user", userVO);
+        return modelAndView;
+    }
+
 }

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

@@ -4,6 +4,7 @@ import cn.iselab.mooctest.rpc.user.data.UserDTO;
 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.model.User;
 import cn.iselab.mooctest.user.util.EncryptionUtil;
 import cn.iselab.mooctest.user.web.data.UserVO;
 import cn.iselab.mooctest.user.web.logic.UserLogic;
@@ -77,7 +78,7 @@ public class UserController extends BaseController {
         return result;
     }
 
-    @RequestMapping(value = UrlConstants.API + "mobile/login", method = RequestMethod.GET)
+    @RequestMapping(value = UrlConstants.API + "mobile/login", method =  RequestMethod.GET)
     public ResponseResult<Object> mobileLogin(UserVO userVO, HttpServletRequest request){
         return null;
     }
@@ -94,5 +95,23 @@ public class UserController extends BaseController {
         return userLogic.sendMobileVerfication(userDTO);
     }
 
+    @RequestMapping(value = UrlConstants.API + "password/reset", method = RequestMethod.PUT)
+    public ResponseResult<UserVO> resetPassword(@RequestBody UserVO userVO){
+        return userLogic.resetPassword(userVO);
+    }
+
+    @RequestMapping(value = UrlConstants.API + "user/password", method = RequestMethod.PUT)
+    public ResponseResult<UserVO> updatePassword(@RequestBody UserVO userVO, HttpServletRequest request){
+        return userLogic.updateUserPassword(userVO, request);
+    }
 
+    @RequestMapping(value = UrlConstants.API + "user/email", method = RequestMethod.PUT)
+    public ResponseResult<UserVO> updateEmail(@RequestBody UserVO userVO, HttpServletRequest request){
+        return userLogic.updateUserEmail(userVO, request);
+    }
+
+    @RequestMapping(value = UrlConstants.API + "user/mobile", method = RequestMethod.PUT)
+    public ResponseResult<UserVO> updateMobile(@RequestBody UserVO userVO, HttpServletRequest request){
+        return userLogic.updateUserMobile(userVO, request);
+    }
 }

+ 2 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/data/UserVO.java

@@ -15,4 +15,6 @@ public class UserVO extends UserDTO {
    private String verifyCode;
 
    private String password2;
+
+   private String oldPassword;
 }

+ 55 - 0
mooctest-user-server/src/main/java/cn/iselab/mooctest/user/web/data/UserVOWrapper.java

@@ -0,0 +1,55 @@
+package cn.iselab.mooctest.user.web.data;
+
+import cn.iselab.mooctest.user.model.User;
+import cn.iselab.mooctest.user.web.wrapper.BaseWrapper;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+
+/**
+ * @Description: 作用描述
+ * @Author: xuexb
+ * @CreateDate: 19-1-2$ 上午2:21$
+ */
+@Service
+public class UserVOWrapper extends BaseWrapper<UserVO, User> {
+
+    @Override
+    public UserVO wrap(User user) {
+        UserVO userVO = new UserVO();
+
+        userVO.setAvailability(user.getAvailability());
+        userVO.setCity(user.getCity());
+        userVO.setCreateTime(user.getCreateTime().getTime());
+        userVO.setEmail(user.getEmail());
+        userVO.setId(user.getId());
+        userVO.setManualCheckValid(user.getManualCheckValid());
+        userVO.setMobile(user.getMobile());
+        userVO.setName(user.getName());
+        userVO.setPassword(user.getPassword());
+        userVO.setPhotoUrl(user.getPhotoUrl());
+        userVO.setProvince(user.getProvince());
+        userVO.setSchool(user.getSchool());
+        return userVO;
+    }
+
+    @Override
+    public User unwrap(UserVO data) {
+        User user = new User();
+
+        user.setSchool(data.getSchool());
+        user.setProvince(data.getProvince());
+        user.setPhotoUrl(data.getPhotoUrl());
+        user.setAvailability(data.getAvailability());
+        user.setCity(data.getCity());
+        user.setCreateTime(new Timestamp(data.getCreateTime()));
+        user.setEmail(data.getEmail());
+        user.setId(data.getId());
+        user.setManualCheckValid(data.getManualCheckValid());
+        user.setMobile(data.getMobile());
+        user.setName(data.getName());
+        user.setPassword(data.getPassword());
+
+        return user;
+    }
+}

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

@@ -5,6 +5,7 @@ import cn.iselab.mooctest.user.constants.ResponseStatus;
 import cn.iselab.mooctest.user.data.ResponseResult;
 import cn.iselab.mooctest.user.web.data.UserVO;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 
 /**
@@ -45,7 +46,15 @@ public interface UserLogic {
 
     ResponseResult<UserDTO> loginByMobile(UserVO userVO);
 
+    ResponseResult<UserVO> checkVerifyCode(UserVO userVO, String type);
 
+    ResponseResult<UserVO> resetPassword(UserVO userVO);
+
+    ResponseResult<UserVO> updateUserPassword(UserVO userVO, HttpServletRequest request);
+
+    ResponseResult<UserVO> updateUserEmail(UserVO userVO, HttpServletRequest request);
+
+    ResponseResult<UserVO> updateUserMobile(UserVO userVO, HttpServletRequest request);
 
 
 }

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

@@ -15,15 +15,19 @@ import cn.iselab.mooctest.user.service.VerifyCodeService;
 import cn.iselab.mooctest.user.util.EncryptionUtil;
 import cn.iselab.mooctest.user.util.MSUtil;
 import cn.iselab.mooctest.user.web.data.UserVO;
+import cn.iselab.mooctest.user.web.data.UserVOWrapper;
 import cn.iselab.mooctest.user.web.exception.HttpBadRequestException;
 import cn.iselab.mooctest.user.web.logic.BaseLogic;
 import cn.iselab.mooctest.user.web.logic.UserLogic;
 import cn.iselab.mooctest.user.web.wrapper.UserWrapper;
+import com.alibaba.dubbo.rpc.filter.EchoFilter;
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.validator.routines.EmailValidator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.mail.MessagingException;
+import javax.servlet.http.HttpServletRequest;
 import java.sql.Timestamp;
 import java.util.List;
 
@@ -52,6 +56,9 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
     @Autowired
     private MailProperties mailProperties;
 
+    @Autowired
+    private UserVOWrapper userVOWrapper;
+
     @Override
     public UserDTO getUserByEmail(String s) {
         User user = userService.findByEmail(s);
@@ -117,6 +124,7 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
             LOG.error("账号和密码不可为空");
             return result;
         }
+
         User user;
         try {
             user = (!userDTO.getEmail().isEmpty())?
@@ -301,13 +309,13 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
     public ResponseResult<String> sendVerifyEmail(UserDTO userDTO) {
         String receiver = userDTO.getEmail();
         ResponseResult<String> result = new ResponseResult<>();
-        if(userService.findByEmail(userDTO.getEmail()) != null){
-            result.init(ResponseStatus.FAILED, "该邮箱已被注册", receiver);
-            LOG.error(result.getMsg());
-            return result;
-        }
+//        if(userService.findByEmail(userDTO.getEmail()) != null){
+//            result.init(ResponseStatus.FAILED, "该邮箱已被注册", receiver);
+//            LOG.error(result.getMsg());
+//            return result;
+//        }
         if (!EmailValidator.getInstance().isValid(userDTO.getEmail())){
-            result.init(ResponseStatus.FAILED, "注册邮箱非法", receiver);
+            result.init(ResponseStatus.FAILED, "邮箱输入非法", receiver);
             LOG.error(result.getMsg());
             return result;
         }
@@ -369,7 +377,7 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
                     + VerifyConstants.TIME_OUT));
             verifyCodeService.saveVerifyCode(verifyCode);
             result.init(ResponseStatus.SUCCESS, "短信发送成功", receiver);
-            LOG.info(result.getMsg() + ", mobile: " + receiver);
+            LOG.info(result.getMsg() + ", mobile: " + receiver + " code: " +code);
         }else{
             if (sendResult.equals(arrearsCode)){
                 mailService.sendArrearsEmail();
@@ -409,5 +417,201 @@ public class UserLogicImpl extends BaseLogic implements UserLogic {
         return result;
     }
 
+    @Override
+    public ResponseResult<UserVO> checkVerifyCode(UserVO userVO, String type){
+        ResponseResult<UserVO> result = new ResponseResult<>();
+        if (type.equals("email")){
+            if (!EmailValidator.getInstance().isValid(userVO.getEmail())){
+                result.init(ResponseStatus.FAILED, "邮箱输入非法", userVO);
+                LOG.error(result.getMsg() + " email: " + userVO.getEmail());
+                return result;
+            }
+            if(! verifyCodeService.validateVerifyCode("email", userVO.getEmail(), userVO.getVerifyCode())){
+                result.init(ResponseStatus.FAILED, "请确认邮箱及验证码输入正确", userVO);
+                LOG.error(result.getMsg());
+                return result;
+            }
+
+            User user = userService.findByEmail(userVO.getEmail());
+            if (user == null){
+                result.init(ResponseStatus.FAILED, "用户不存在", userVO);
+                LOG.error(result.getMsg());
+                return result;
+            }
+            try{
+                userVO = resetCodeStr(user);
+                result.init(ResponseStatus.SUCCESS, "验证码输入正确", userVO);
+                LOG.info(result.getMsg() + " email: " + userVO.getEmail()+ " code: " + userVO.getVerifyCode());
+                return result;
+            }catch (Exception e){
+                LOG.error("重置密码加密口令出错", e);
+                result.init(ResponseStatus.FAILED, "系统繁忙", null);
+                return result;
+            }
+
+        }
+
+        if (type.equals("mobile")){
+            if (userVO.getMobile() == null || !MSUtil.isMobileNO(userVO.getMobile())){
+                result.init(ResponseStatus.FAILED, "手机号不正确", userVO);
+                LOG.error(result.getMsg() + userVO.getMobile());
+                return result;
+            }
+            if(!verifyCodeService.validateVerifyCode("mobile", userVO.getMobile(), userVO.getVerifyCode())){
+                result.init(ResponseStatus.FAILED, "手机号或验证码不正确", userVO);
+                LOG.error(result.getMsg());
+                return result;
+            }
+            User user = userService.findByMobile(userVO.getMobile());
+            if (user == null){
+                result.init(ResponseStatus.FAILED, "该手机号未绑定慕测账号", userVO);
+                LOG.error(result.getMsg() + userVO.getMobile());
+                return result;
+            }
+            try{
+                userVO = resetCodeStr(user);
+                result.init(ResponseStatus.SUCCESS, "验证码输入正确", userVO);
+                LOG.info(result.getMsg() + " email: " + userVO.getMobile()+ " code: " + userVO.getVerifyCode());
+                return result;
+            } catch (Exception e){
+                LOG.error("重置密码加密口令出错", e);
+                result.init(ResponseStatus.FAILED, "系统繁忙", null);
+                return result;
+            }
+
+
+        }
+
+        result.init(ResponseStatus.FAILED, "验证出错", userVO);
+        LOG.error(result.getMsg());
+        return result;
+    }
+
+
+    @Override
+    public ResponseResult<UserVO> resetPassword(UserVO userVO){
+        ResponseResult<UserVO> result = new ResponseResult<>();
+        String encrypt = userVO.getVerifyCode();
+        try{
+            String base64DecodeStr = new String(Base64.decodeBase64(encrypt.getBytes("UTF-8")));
+            String decrypt = EncryptionUtil.decryptDES(base64DecodeStr);
+            String[] items = decrypt.split("_");
+            long userId = Long.valueOf(items[1]);
+            long expireTime = Long.valueOf(items[2]);
+            if (expireTime < System.currentTimeMillis()){
+                throw new Exception("验证已过期");
+            }
+            User user = userService.findById(userId);
+            if (user == null){
+                throw new Exception("用户不存在");
+            }
+            if (userVO.getPassword().length() > 16 || userVO.getPassword().length() < 6){
+                throw new Exception("密码长度应在6-16位");
+            }
+            user.setPassword(EncryptionUtil.encryptMD5(userVO.getPassword()));
+            user = userService.update(user);
+            userVO = userVOWrapper.wrap(user);
+            result.init(ResponseStatus.SUCCESS, "密码重置成功", userVO);
+            LOG.info(result.getMsg() + "userId: " + userVO.getId());
+        } catch (Exception e){
+            result.init(ResponseStatus.FAILED, e.getMessage(), userVO);
+            LOG.error(result.getMsg(), e);
+            return result;
+        }
+        return result;
+    }
+
+    private UserVO resetCodeStr(User user) throws Exception {
+        UserVO userVO = userVOWrapper.wrap(user);
+        String passStr = "user_" + user.getId() + "_" +
+                String.valueOf(System.currentTimeMillis() +
+                        VerifyConstants.TIME_OUT);
+        String encryptStr;
+        encryptStr = EncryptionUtil.encryptDES(passStr);
+        String base64Encrypt = new String(Base64.encodeBase64(encryptStr.getBytes("UTF-8")));
+        String code = base64Encrypt;
+        userVO.setVerifyCode(code);
+        return userVO;
+    }
+
+    @Override
+    public ResponseResult<UserVO> updateUserPassword(UserVO userVO, HttpServletRequest request){
+        ResponseResult<UserVO> result = new ResponseResult<>();
+        Long userId = (Long) request.getSession().getAttribute("userId");
+        try {
+            if (userId == null)
+                throw new Exception("用户未登录");
+            if (userVO.getPassword().length() > 16 || userVO.getPassword().length() < 6){
+                throw new Exception("密码长度应在6-16位");
+            }
+            User user = userService.findById(userId);
+            if (!EncryptionUtil.encryptMD5(userVO.getOldPassword()).equals(user.getPassword()))
+                throw new Exception("旧密码错误");
+
+            String password = EncryptionUtil.encryptMD5(userVO.getPassword());
+            user.setPassword(password);
+            user = userService.update(user);
+            userVO = userVOWrapper.wrap(user);
+            userVO.setPassword("");
+            userVO.setPassword2("");
+            result.init(ResponseStatus.SUCCESS, "密码修改成功", userVO);
+            LOG.info(result.getMsg()+" userId: "+userVO.getId());
+            request.getSession().removeAttribute("userId");
+        } catch (Exception e) {
+            result.init(ResponseStatus.FAILED, e.getMessage(), userVO);
+            LOG.error(result.getMsg(),e);
+            return result;
+        }
+        return result;
+    }
+
+    @Override
+    public ResponseResult<UserVO> updateUserEmail(UserVO userVO, HttpServletRequest request) {
+        ResponseResult<UserVO> result = new ResponseResult<>();
+        Long userId = (Long) request.getSession().getAttribute("userId");
+        try {
+            if (userId == null)
+                throw new Exception("用户未登录");
+            if (!verifyCodeService.validateVerifyCode("email", userVO.getEmail(), userVO.getVerifyCode()))
+                throw new Exception("验证码或邮箱填写错误");
+            User user = userService.findById(userId);
+            if (!userVO.getEmail().equals(user.getEmail()) && userService.findByEmail(userVO.getEmail()) != null)
+                throw new Exception("该邮箱已被注册");
+            user.setEmail(userVO.getEmail());
+            userVO = userVOWrapper.wrap(userService.update(user));
+            result.init(ResponseStatus.SUCCESS, "邮箱修改成功", userVO);
+            LOG.info(result.getMsg() + " userId: "+ userVO.getId() + " email: " + userVO.getEmail());
+        } catch (Exception e){
+            result.init(ResponseStatus.FAILED, e.getMessage(), userVO);
+            LOG.info(result.getMsg(), e);
+            return result;
+        }
+        return result;
+    }
+
+    @Override
+    public ResponseResult<UserVO> updateUserMobile(UserVO userVO, HttpServletRequest request) {
+        ResponseResult<UserVO> result = new ResponseResult<>();
+        Long userId = (Long) request.getSession().getAttribute("userId");
+        try {
+            if (userId == null)
+                throw new Exception("用户未登录");
+            if (!verifyCodeService.validateVerifyCode("mobile", userVO.getMobile(), userVO.getVerifyCode()))
+                throw new Exception("验证码或手机号填写错误");
+            User user = userService.findById(userId);
+            if (!userVO.getMobile().equals(user.getMobile()) && userService.findByMobile(userVO.getMobile()) != null)
+                throw new Exception("该手机号码已被绑定");
+            user.setMobile(userVO.getMobile());
+            userVO = userVOWrapper.wrap(userService.update(user));
+            result.init(ResponseStatus.SUCCESS, "手机号修改成功", userVO);
+            LOG.info(result.getMsg() + " userId: "+ userVO.getId() + " mobile: " + userVO.getMobile());
+        } catch (Exception e){
+            result.init(ResponseStatus.FAILED, e.getMessage(), userVO);
+            LOG.info(result.getMsg(), e);
+            return result;
+        }
+        return result;
+    }
+
 
 }

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

@@ -23,7 +23,7 @@
     <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 id="byEmail" th:action="@{/page/forgetPassword/check}" method="post" class="login100-form">
+            <form id="byEmail" th:action="@{/page/forgetPassword/check/email}" method="post" class="login100-form">
                 <div id="login-logo" class="p-b-15" style="text-align: center;">
                     <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
                 </div>
@@ -67,7 +67,7 @@
                 </div>
             </form>
             <!--手机找回-->
-            <form id="byMobile" style="display: none;" th:action="@{/page/forgetPassword/check}" method="post" class="login100-form">
+            <form id="byMobile" style="display: none;" th:action="@{/page/forgetPassword/check/mobile}" method="post" class="login100-form">
                 <div style="text-align: center;" class="p-b-15">
                     <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
                 </div>

+ 108 - 0
mooctest-user-server/src/main/resources/templates/forget_password_email.html

@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 id="byEmail" th:action="@{/page/forgetPassword/check/email}" method="post" class="login100-form">
+                <div id="login-logo" class="p-b-15" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">找回密码</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入邮箱">
+                    <span class="label-input100">邮箱</span>
+                    <input id="email" class="input100" type="email" name="email" 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-right">
+                        <a href="/page/forgetPassword/mobile">手机找回</a>
+                    </div>
+                </div>
+
+                <div class="text-center p-t-6 p-b-8">
+                    <span id="e_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="sendMobileVerify" class="login100-form-btn" onclick="sendEmailVerifyCode(this)" >获取验证码</button>
+                    </div>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="submit" class="login100-form-btn">验 证</button>
+                    </div>
+                </div>
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/login" class="txt2">返回登录</a>
+                </div>
+            </form>
+            </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 sendEmailVerifyCode(obj) {
+        var email = $("#email").val();
+        if (email == null || email.trim() == "") {
+            document.getElementById("e_info").innerText = "邮箱不能为空";
+            return;
+        }
+        if (!email.match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/)){
+            document.getElementById("e_info").innerText = "邮箱格式不正确,请重新输入";
+            return
+        }
+
+        var data = {"email":email};
+        $.ajax({
+            url:"/api/verify/mail",
+            type:"PUT",
+            data:data,
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    alert("发送失败, 原因:"+result.msg);
+                }else{
+                    alert("发送成功,请前往邮箱查收!");
+                    document.getElementById("e_info").innerHTML = "&nbsp;"
+                    settime(obj);
+                }
+            }
+        })
+    }
+</script>
+</body>
+</html>

+ 107 - 0
mooctest-user-server/src/main/resources/templates/forget_password_mobile.html

@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 id="byMobile" th:action="@{/page/forgetPassword/check/mobile}" method="post" class="login100-form">
+                <div style="text-align: center;" class="p-b-15">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">找回密码</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入手机号">
+                    <span class="label-input100">手机号</span>
+                    <input id="mobile" class="input100" type="text" name="mobile" placeholder="请输入手机号" required="手机号不可为空">
+                    <span class="focus-input100" data-symbol="&#xf2c8;"></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-right">
+                        <a href="/page/forgetPassword/email">邮箱找回</a>
+                    </div>
+                </div>
+
+                <div class="text-center p-t-6 p-b-8">
+                    <span id="m_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="sendMobileVerifyCode(this)" >获取验证码</button>
+                    </div>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="submit" form="byMobile" class="login100-form-btn">验 证</button>
+                    </div>
+                </div>
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/login" 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 sendMobileVerifyCode(obj) {
+        var mobile = $("#mobile").val();
+        if (mobile == null || mobile.trim() == "") {
+            document.getElementById("m_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("m_info").innerText = "手机号格式不正确,请重新输入";
+            return
+        }
+
+        var data = {"mobile":mobile};
+        $.ajax({
+            url:"/api/verify/mobile",
+            type:"PUT",
+            data:data,
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    alert("发送失败, 原因:"+result.msg);
+                    document.getElementById("m_info").innerText = result.msg;
+                }else{
+                    alert("发送成功,请尽快查收!");
+                    document.getElementById("m_info").innerHTML = "&nbsp;";
+                    settime(obj);
+                }
+            }
+        })
+    }
+</script>
+</body>
+</html>

+ 111 - 0
mooctest-user-server/src/main/resources/templates/forget_password_reset.html

@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 method="post" class="login100-form validate-form">
+                <div id="login-logo" class="p-b-15" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">重置密码</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入用户名">
+                    <span class="label-input100">邮箱</span>
+                    <input id="email" class="input100" type="text" name="email" readonly="readonly" th:value="${user.email}">
+                    <span class="focus-input100" data-symbol="&#xf206;"></span>
+                </div>
+
+                <div class="wrap-input100 validate-input m-b-23"  data-validate="请输入密码">
+                    <span class="label-input100">新密码</span>
+                    <input id="password" class="input100" type="password" name="password" placeholder="请输入密码" required="密码不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </div>
+                <input id="verifyCode" name="verifyCode" style="display: none" th:value="${user.verifyCode}">
+                <div class="wrap-input100 validate-input" data-validate="请输入密码">
+                    <span class="label-input100">重复密码</span>
+                    <input id="password2" class="input100" type="password" name="password2" placeholder="请输入密码" required="密码不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </div>
+
+                <div class="text-center p-t-6 p-b-20">
+                    <span id="info" style="color: red" th:text="${result==null}?'&nbsp;':${result.msg}"></span>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="button" onclick="resetPassword(this)" class="login100-form-btn">重置密码</button>
+                    </div>
+                </div>
+
+
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/login" 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 resetPassword(obj) {
+        var email = $("#email").val();
+        var password = $("#password").val();
+        var password2 = $("#password2").val();
+        var verifyCode = $("#verifyCode").val();
+        if (password == null || password.trim() == ""
+        || password2 == null || password2.trim() == "") {
+            document.getElementById("info").innerText = "密码不可为空";
+            return;
+        }
+        if (password != password2){
+            document.getElementById("info").innerText = "密码不一致,请重新输入";
+            return;
+        }
+        if (password.length>16 || password.length<6){
+            document.getElementById("info").innerText = "密码应在6-16位";
+            return;
+        }
+        var data = {"email":email, "password":password, "verifyCode":verifyCode};
+        $.ajax({
+            url:"/api/password/reset",
+            type:"PUT",
+            data:JSON.stringify(data),
+            contentType: 'application/json; charset=utf-8',
+            dataType:"json",
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    document.getElementById("info").innerText = result.msg;
+                }else{
+                    alert("修改成功,请前往登录");
+                    document.location.href="/page/login";
+                }
+            }
+        })
+    }
+</script>
+</body>
+</html>

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

@@ -46,7 +46,7 @@
                         <a href="/page/mobile/login">手机登录</a>
                     </div>
                     <div class="text-right" style="float: right;">
-                        <a href="/page/forgetPassword">忘记密码?</a>
+                        <a href="/page/forgetPassword/email">忘记密码?</a>
                     </div>
                 </div>
                 <div class="text-center p-t-6 p-b-20">

+ 137 - 0
mooctest-user-server/src/main/resources/templates/reset_email.html

@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 id="byEmail" th:action="@{/api/user/email}" method="post" class="login100-form">
+                <div id="login-logo" class="p-b-15" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">修改邮箱</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入邮箱">
+                    <span class="label-input100">新邮箱</span>
+                    <input id="email" class="input100" type="email" name="email" 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 id="verifyCode" class="input100" type="text" name="verifyCode" placeholder="请输入验证码" required="验证码不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </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="sendMobileVerify" class="login100-form-btn" onclick="sendEmailVerifyCode(this)" >获取验证码</button>
+                    </div>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="button" onclick="updateEmail()" class="login100-form-btn">验 证</button>
+                    </div>
+                </div>
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/login" class="txt2">返回登录</a>
+                </div>
+            </form>
+            </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 sendEmailVerifyCode(obj) {
+        var email = $("#email").val();
+        if (email == null || email.trim() == "") {
+            document.getElementById("info").innerText = "邮箱不能为空";
+            return;
+        }
+        if (!email.match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/)){
+            document.getElementById("info").innerText = "邮箱格式不正确,请重新输入";
+            return
+        }
+
+        var data = {"email":email};
+        $.ajax({
+            url:"/api/verify/mail",
+            type:"PUT",
+            data:data,
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    alert("发送失败, 原因:"+result.msg);
+                }else{
+                    alert("发送成功,请前往邮箱查收!");
+                    document.getElementById("info").innerHTML = "&nbsp;"
+                    settime(obj);
+                }
+            }
+        })
+    }
+
+    function updateEmail() {
+        var email = $("#email").val();
+        var verifyCode = $("#verifyCode").val();
+        if (email == null || email.trim() == "") {
+            document.getElementById("info").innerText = "邮箱不能为空";
+            return;
+        }
+        if (!email.match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/)){
+            document.getElementById("info").innerText = "邮箱格式不正确,请重新输入";
+            return;
+        }
+        if (verifyCode == null || verifyCode.trim()==""){
+            document.getElementById("info").innerText = "请填写验证码";
+            return;
+        }
+        var data = {"email":email, "verifyCode":verifyCode};
+        $.ajax({
+            url:"/api/user/email",
+            type:"PUT",
+            data:JSON.stringify(data),
+            contentType: 'application/json; charset=utf-8',
+            dataType:"json",
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    document.getElementById("info").innerText = result.msg;
+                }else{
+                    document.location.href="/page/operation/success";
+                }
+            }
+        })
+
+    }
+</script>
+</body>
+</html>

+ 138 - 0
mooctest-user-server/src/main/resources/templates/reset_mobile.html

@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 id="byEmail" th:action="@{/api/user/mobile}" method="post" class="login100-form">
+                <div id="login-logo" class="p-b-15" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">修改手机号</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入邮箱">
+                    <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 id="verifyCode" class="input100" type="text" name="verifyCode" placeholder="请输入验证码" required="验证码不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </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="sendMobileVerify" class="login100-form-btn" onclick="sendMobileVerifyCode(this)" >获取验证码</button>
+                    </div>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="button" onclick="updateMobile()" class="login100-form-btn">验 证</button>
+                    </div>
+                </div>
+                <div class="flex-col-c p-t-10">
+                    <a href="/page/login" class="txt2">返回登录</a>
+                </div>
+            </form>
+            </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 sendMobileVerifyCode(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:"PUT",
+            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);
+                }
+            }
+        })
+    }
+
+    function updateMobile() {
+        var mobile = $("#mobile").val();
+        var verifyCode = $("#verifyCode").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
+        }
+        if (verifyCode == null || verifyCode.trim()==""){
+            document.getElementById("info").innerText = "请填写验证码";
+            return;
+        }
+        var data = {"mobile":mobile, "verifyCode":verifyCode};
+        $.ajax({
+            url:"/api/user/mobile",
+            type:"PUT",
+            data:JSON.stringify(data),
+            contentType: 'application/json; charset=utf-8',
+            dataType:"json",
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    document.getElementById("info").innerText = result.msg;
+                }else{
+                    document.location.href="/page/operation/success";
+                }
+            }
+        })
+
+    }
+</script>
+</body>
+</html>

+ 105 - 0
mooctest-user-server/src/main/resources/templates/reset_password.html

@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:th="http://www.thymeleaf.org">
+
+<head>
+    <meta charset="UTF-8">
+    <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 method="post" class="login100-form validate-form">
+                <div id="login-logo" class="p-b-15" style="text-align: center;">
+                    <img style="width: 80px;" th:src="@{/images/mooctest.png}" >
+                </div>
+
+                <span class="login100-form-title p-b-30">修改密码</span>
+
+                <div class="wrap-input100 validate-input m-b-23" data-validate="请输入原密码">
+                    <span class="label-input100">原密码</span>
+                    <input id="oldPassword" class="input100" type="password" name="oldPassword" placeholder="请输入原密码" required="不可为空">
+                    <span class="focus-input100" data-symbol="&#xf206;"></span>
+                </div>
+
+                <div class="wrap-input100 validate-input m-b-23"  data-validate="请输入密码">
+                    <span class="label-input100">新密码</span>
+                    <input id="password" class="input100" type="password" name="password" placeholder="请输入新密码" required="不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </div>
+                <div class="wrap-input100 validate-input" data-validate="请输入密码">
+                    <span class="label-input100">重复密码</span>
+                    <input id="password2" class="input100" type="password" name="password2" placeholder="请确认新密码" required="不可为空">
+                    <span class="focus-input100" data-symbol="&#xf190;"></span>
+                </div>
+
+                <div class="text-center p-t-6 p-b-20">
+                    <span id="info" style="color: red" th:text="${result==null}?'&nbsp;':${result.msg}"></span>
+                </div>
+                <div class="container-login100-form-btn">
+                    <div class="wrap-login100-form-btn">
+                        <div class="login100-form-bgbtn"></div>
+                        <button type="button" onclick="resetPassword(this)" class="login100-form-btn">重置密码</button>
+                    </div>
+                </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 resetPassword(obj) {
+        var oldPassword = $("#oldPassword").val();
+        var password = $("#password").val();
+        var password2 = $("#password2").val();
+        if (oldPassword == null || oldPassword.trim() == ""
+            ||password == null || password.trim() == ""
+            || password2 == null || password2.trim() == "") {
+            document.getElementById("info").innerText = "密码不可为空";
+            return;
+        }
+        if (password != password2){
+            document.getElementById("info").innerText = "密码不一致,请重新输入";
+            return
+        }
+        if (password.length>16 || password.length<6){
+            document.getElementById("info").innerText = "密码应在6-16位";
+            return;
+        }
+        var data = {"oldPassword":oldPassword, "password":password};
+        $.ajax({
+            url:"/api/user/password",
+            type:"PUT",
+            data:JSON.stringify(data),
+            contentType: 'application/json; charset=utf-8',
+            dataType:"json",
+            timeout: 3000,
+            success:function (result) {
+                console.log(result);
+                if (result.status != 2000) {
+                    document.getElementById("info").innerText = result.msg;
+                }else{
+                    alert("修改成功,请前往登录");
+                    document.location.href="/page/login";
+                }
+            }
+        })
+    }
+</script>
+</body>
+</html>

+ 0 - 11
mooctest-user-server/src/main/resources/templates/test_success.html

@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>Test_Success</title>
-</head>
-<body>
-<h1>This is a test page!</h1>
-<h2>Login Succes!!!!!</h2>
-</body>
-</html>