出于某些考虑,博客采用邮箱注册方式

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">&times;</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">&times;</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

项目地址