出于某些考虑,博客采用邮箱注册方式
1. 编写登录界面
去掉了Spring Security以后,自己编写登录登出接口,然后登录采用的方式是弹出框方式,也就是利用bootstrap中的modal
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalCenterTitle" style="color:black">LoginIn</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body" id="receiverShow" style="color:black"> <form> <div class="form-group"> <label for="LoginModalEmail">Email</label> <input type="email" class="form-control" id="LoginModalEmail" placeholder="Email"> <div class="invalid-feedback"> 请输入正确的Email </div> </div> <div class="form-group"> <label for="LoginModalPassword">Password</label> <input type="password" class="form-control" id="LoginModalPassword" placeholder="password"> <div class="invalid-feedback"> 密码长度不小于6,只能包含数字字母和标点符号 </div> </div> </form> </div> <div class="modal-footer"> <a id="LoginInFormMessage"></a> <button type="button" class="btn btn-secondary" id="GoToRegisterFromLogin">注册</button> <button type="button" class="btn btn-secondary" id="LoginInButton">LoginIn</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div>
在js中判断输入是否符合要求
$("#LoginModalEmail").bind("input propertychange",function () { if(isValidEMail($("#LoginModalEmail").val())){ if($("#LoginModalEmail").hasClass("is-invalid")){ $("#LoginModalEmail").removeClass("is-invalid"); } }else{ if(!$("#LoginModalEmail").hasClass("is-invalid")){ $("#LoginModalEmail").addClass("is-invalid"); } } }); $("#LoginModalPassword").bind("input propertychange",function () { if($('#LoginModalPassword').val().length>6){ if($("#LoginModalPassword").hasClass("is-invalid")){ $("#LoginModalPassword").removeClass("is-invalid"); } }else{ if(!$("#LoginModalPassword").hasClass("is-invalid")){ $("#LoginModalPassword").addClass("is-invalid"); } } }); $("#LoginInButton").click(function () { if(!isValidEMail($("#LoginModalEmail").val())){ if(!$("#LoginModalEmail").hasClass("is-invalid")){ $("#LoginModalEmail").addClass("is-invalid"); } }else if($('#LoginModalPassword').val().length<=6){ if(!$("#LoginModalPassword").hasClass("is-invalid")){ $("#LoginModalPassword").addClass("is-invalid"); } } else { if ($('#LoginModalEmail').val() != "" && $('#LoginModalPassword').val() != "") { $.post("/user/login", { email: $("#LoginModalEmail").val(), password: $("#LoginModalPassword").val() }, function (data, status) { if (data.state && data.state == 1) { $("#LoginInFormMessage").hide(); window.location.reload(); } else { $("#LoginInFormMessage").show(); $("#LoginInFormMessage").text("Password or email error"); } }); } } });
2. 编写注册界面
<div class="modal fade" id="RegisterModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" style="color:black">注册</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body" style="color:black"> <form> <div class="form-group"> <label for="RegisterModalEmail">Email</label> <input type="email" class="form-control" id="RegisterModalEmail" placeholder="Email"> <div class="invalid-feedback"> 请输入正确的Email,不要使用被别人注册过的email </div> </div> <div class="form-group"> <label for="RegisterModalUserName">Username</label> <input type="text" class="form-control" id="RegisterModalUserName"> <div class="invalid-feedback"> 用户名长度小于10 </div> </div> <div class="form-row"> <div class="form-group col-md-6"> <label for="RegisterModalPassword">Password</label> <input type="password" class="form-control" id="RegisterModalPassword" placeholder="password"> <div class="invalid-feedback"> 密码长度不小于6,只能包含数字字母和标点符号 </div> </div> <div class="form-group col-md-6"> <label for="RegisterModalRepeatPassword">Repeat Password</label> <input type="password" class="form-control" id="RegisterModalRepeatPassword" placeholder="Password"> <div class="invalid-feedback"> 请保持前后输入密码一致 </div> </div> </div> <div class="form-row"> <div class="form-group col-md-8"> <label for="RegisterModalAuthCode">验证码</label> <input type="number" class="form-control" id="RegisterModalAuthCode"> <div class="invalid-feedback"> 请输入验证码,验证码可能出现在垃圾箱中 </div> </div> <div class="form-group col-md-4"> <label for="RegisterModalGetAuthCode" style="color: #FFFFFF">验证码</label> <button type="button" class="btn btn-secondary" id="RegisterModalGetAuthCode">获取验证码</button> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" id="RegisterModalButton">注册</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div>
相关的js为
function isValidEMail(email){ if(email){ var reg = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/; if(!reg.test(email)){ return false; }else{ return true; } }else{ return false; } } //检测Email是否输入正确 $("#RegisterModalEmail").bind("input propertychange",function () { if(isValidEMail($("#RegisterModalEmail").val())){ if($("#RegisterModalEmail").hasClass("is-invalid")){ $("#RegisterModalEmail").removeClass("is-invalid"); } }else{ if(!$("#RegisterModalEmail").hasClass("is-invalid")){ $("#RegisterModalEmail").addClass("is-invalid"); } } }); //检测用户名长度是否大于10 $("#RegisterModalUserName").bind("input propertychange",function () { if($("#RegisterModalUserName").val().length<=10){ if($("#RegisterModalUserName").hasClass("is-invalid")){ $("#RegisterModalUserName").removeClass("is-invalid"); } }else{ if(!$("#RegisterModalUserName").hasClass("is-invalid")){ $("#RegisterModalUserName").addClass("is-invalid"); } } }); $("#RegisterModalPassword").bind("input propertychange",function () { if($("#RegisterModalPassword").val().length>6){ if($("#RegisterModalPassword").hasClass("is-invalid")){ $("#RegisterModalPassword").removeClass("is-invalid"); } }else{ if(!$("#RegisterModalPassword").hasClass("is-invalid")){ $("#RegisterModalPassword").addClass("is-invalid"); } } }); //检测重复密码是否正确 $("#RegisterModalRepeatPassword").bind("input propertychange",function () { if($("#RegisterModalRepeatPassword").val()==$("#RegisterModalPassword").val()){ if($("#RegisterModalRepeatPassword").hasClass("is-invalid")){ $("#RegisterModalRepeatPassword").removeClass("is-invalid"); } }else{ if(!$("#RegisterModalRepeatPassword").hasClass("is-invalid")){ $("#RegisterModalRepeatPassword").addClass("is-invalid"); } } }); $("#RegisterModalAuthCode").bind("input propertychange",function () { if($("#RegisterModalAuthCode").val()>=100000&&$("#RegisterModalAuthCode").val()<=999999){ if($("#RegisterModalAuthCode").hasClass("is-invalid")){ $("#RegisterModalAuthCode").removeClass("is-invalid"); } }else{ if(!$("#RegisterModalAuthCode").hasClass("is-invalid")){ $("#RegisterModalAuthCode").addClass("is-invalid"); } } }); //获取验证码 $("#RegisterModalGetAuthCode").click(function () { if(isValidEMail($("#RegisterModalEmail").val())) { $.post("/user/getAuthCode",{ to:$("#RegisterModalEmail").val() },function (data,status) { if(data&&data.state){ if(data.state=="-1"){ //-1说明已经被注册了 if(!$("#RegisterModalEmail").hasClass("is-invalid")){ $("#RegisterModalEmail").addClass("is-invalid"); } }else{ $("#RegisterModalGetAuthCode").attr("disable","true"); } } }) } }); $("#RegisterModalButton").click(function () { //先需要判断所有的输入是否正确 if($("#RegisterModalAuthCode").val()<100000||$("#RegisterModalAuthCode").val()>999999){ if(!$("#RegisterModalAuthCode").hasClass("is-invalid")){ $("#RegisterModalAuthCode").addClass("is-invalid"); } }else if(!isValidEMail($("#RegisterModalEmail").val())){ if(!$("#RegisterModalEmail").hasClass("is-invalid")){ $("#RegisterModalEmail").addClass("is-invalid"); } }else if($("#RegisterModalUserName").val().length>10){ if(!$("#RegisterModalUserName").hasClass("is-invalid")){ $("#RegisterModalUserName").addClass("is-invalid"); } }else if($("#RegisterModalPassword").val().length<=6){ if(!$("#RegisterModalPassword").hasClass("is-invalid")){ $("#RegisterModalPassword").addClass("is-invalid"); } }else if($("#RegisterModalRepeatPassword").val()!=$("#RegisterModalPassword").val()){ if(!$("#RegisterModalRepeatPassword").hasClass("is-invalid")){ $("#RegisterModalRepeatPassword").addClass("is-invalid"); } }else{ $.post("/createUser",{ username:$("#RegisterModalUserName").val(), password:$("#RegisterModalPassword").val(), email:$("#RegisterModalEmail").val(), authCode:$("#RegisterModalAuthCode").val() },function (data,status) { console.log(data); if(data&&data.state){ if(data.state==1){ $("#RegisterModal").modal('hide'); $("#exampleModalCenter").modal('show'); } } }) } });
然后是js判断click事件
$("#logInOrLogout").click(function () { // console.log("click here"); console.log($("#logInOrLogout").text()); if($("#logInOrLogout").text()=="Logout"){ userLoginOut(); }else{ $("#LoginInFormMessage").hide(); $("#exampleModalCenter").modal('show'); } }); $("#GoToRegisterFromLogin").click(function () { $("#exampleModalCenter").modal('hide'); $("#RegisterModal").modal('show'); });
3. 编写login/logout controller
login比较简单,处理步骤就是判断email和password是否输入正确,然后通过判断是否和数据库中的相同,如果相同,则将session写入缓存,logout就是将存储在redis中的session缓存删除
@RequestMapping(value = "/user/login",method = RequestMethod.POST) public @ResponseBody Map<String,String> userLoginIn(String email, String password, HttpServletRequest request){ Map<String,String> map=new HashMap<>(); if(!email.equals("")&&!password.equals("")){ User user = userService.findUserByUserEmailAndPassword(email,password); if(user!=null){ HttpSession session=request.getSession(); session.setAttribute(StaticConfigParam.LOGIN_IN_USER_ID,user.getId()); map.put("state","1"); }else{ map.put("state","0"); } }else { map.put("state","-1"); } return map; } @RequestMapping(value = "/user/logout",method = RequestMethod.POST) public @ResponseBody Map<String,String> userLogOut(HttpServletRequest request){ Map<String,String> map=new HashMap<>(); HttpSession session=request.getSession(); if(session.getAttribute(StaticConfigParam.LOGIN_IN_USER_ID)!=null) session.removeAttribute(StaticConfigParam.LOGIN_IN_USER_ID); map.put("state","1"); return map; }
4. email验证吗相关设置
1. 获取授权码
打开网易邮箱的客户端授权密码(其他邮箱类似)
2. 引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
3. Spring boot properties设置
由于我采用的dev环境和prod环境使用的邮箱相同,因此将邮箱的设置放在application.properties中
4. 编写SendEmailService接口及其实现类
public interface SendEmailService { void sendSimpleEmail(String to,String subject,String content); boolean sendRegisterEmail(String to); int getRegisterAuthCode(String to); boolean deleteRegisterAuthCode(String to); void sendHtmlEmail(String to,String subject,String content); }
在实现类中的具体操作是生成一个6位验证码,将验证码存入redis并发送给用户填写的邮箱地址,如果后面用户能够验证通过,就会从redis中删除该验证码
import com.nevergetme.nevergetmeweb.config.StaticConfigParam; import com.nevergetme.nevergetmeweb.service.SendEmailService; import com.nevergetme.nevergetmeweb.utility.ContentUtility; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; @Service public class SendEmailServiceImpl implements SendEmailService { @Value("${spring.mail.username}") private String whoAmI; @Autowired private JavaMailSender mailSender; @Autowired private RedisTemplate redisTemplate; @Override /** * @description: TODO * @param [to, subject, content] * @return void * @throws * @author Alden He * @date 2019/5/3 21:16 */ public void sendSimpleEmail(String to, String subject, String content) { SimpleMailMessage message=new SimpleMailMessage(); message.setTo(to); message.setSubject(subject); message.setText(content); message.setFrom(whoAmI); mailSender.send(message); } @Override /** * @description: TODO * @param [to] * @return boolean * @throws * @author Alden He * @date 2019/5/3 21:19 */ public boolean sendRegisterEmail(String to) { String key=StaticConfigParam.REGISTER_EMAIL_CODE_REDIS+to; if(!redisTemplate.hasKey(key)){ SimpleMailMessage message=new SimpleMailMessage(); message.setTo(to); message.setSubject(StaticConfigParam.REGISTER_SEND_EMAIL_SUBJECT); int authCode=ContentUtility.getRandomInteger(); message.setText(StaticConfigParam.REGISTER_SEND_EMAIL_CONTENT+ authCode); message.setFrom(whoAmI); mailSender.send(message); redisTemplate.opsForValue().set(key,authCode); return true; }else{ return false; } } /** * 获取存储在redis中的验证码 * @param to * @return */ @Override public int getRegisterAuthCode(String to) { String key=StaticConfigParam.REGISTER_EMAIL_CODE_REDIS+to; if(redisTemplate.hasKey(key)){ return (Integer) redisTemplate.opsForValue().get(key); } return 0; } /** * 删除存储在redis中的验证码 * @param to * @return */ @Override public boolean deleteRegisterAuthCode(String to) { String key=StaticConfigParam.REGISTER_EMAIL_CODE_REDIS+to; if(redisTemplate.hasKey(key)){ redisTemplate.delete(key); } return true; } @Override public void sendHtmlEmail(String to, String subject, String content) { } }
5. email相关的controller
@RequestMapping(value = "/user/sendEmail",method = RequestMethod.POST) public @ResponseBody Map<String,String> sendEmail( @RequestParam(value = "to", required = true) String to, @RequestParam(value = "subject", required = true) String subject, @RequestParam(value = "content", required = true) String content ){ Map<String,String> map=new HashMap<>(); sendEmailService.sendSimpleEmail(to,subject,content); map.put("state","1"); return map; } @RequestMapping(value = "/user/getAuthCode",method = RequestMethod.POST) public @ResponseBody Map<String,String> getAuthCode(@RequestParam(value = "to", required = true) String to){ Map<String,String> map=new HashMap<>(); User user=userService.findUserByEmail(to); if(user==null){ if (sendEmailService.sendRegisterEmail(to)) { map.put("state", "1"); } else { map.put("state", "0"); } }else{ map.put("state","-1"); map.put("message","你已经注册过了!"); } return map; }
6. 阿里云服务器的相关设置
在生产环境中,由于阿里云服务器关闭了25端口,因此需要更换端口,需要在prod环境中增加如下设置
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory spring.mail.properties.mail.smtp.auth=true spring.mail.port=465