Spring-Boot-Full Stack Development: Beautiful Mail Registration

Design sketch

Registration process

1. [Front End] Users submit registration information on the registration page; 2. [Backend] Verify the parameters submitted by the user, return error information directly and execute downward without error; 3. [Backend] Randomly generates an ID with ID as key and user information as value, which is stored in redis for a set period of time; 4. [Backend] Generate an activation link to send mail to the user's mailbox through the mail system 5. [Front End] Users click on the image above to confirm registration; 6. [Backend] Verify that the value expires, that the mailbox is registered, and that the user information is saved to the database, indicating that the user has successfully registered;

Functional implementation (reverse analysis)

1. First look at the implementation of cn.ictgu.tools.mail.MailService for mail delivery

package cn.ictgu.tools.mail;

import cn.ictgu.dao.model.User;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

/**
 * mail serve
 * Created by Silence on 2017/3/11.
 */
@Service
@Log4j
public class MailService {

  @Autowired
  private JavaMailSender mailSender;

  @Value("${spring.mail.username}")
  private String from;

  private static final String TITLE_SIGN_UP = "[Mail Title]";

  private static final String CONTENT = "[Mail Content]";

  public void userValidate(User user, String token){
    MimeMessage mailMessage = mailSender.createMimeMessage();
    try {
      MimeMessageHelper helper = new MimeMessageHelper(mailMessage, true, "GBK");
      helper.setFrom(from);
      helper.setTo(user.getEmail());
      helper.setSubject(TITLE_SIGN_UP);
      String link = "http://www.ictgu.cn/validate/" + token;
      String message = String.format(CONTENT, user.getNickname(), link, link, user.getEmail());
      helper.setText(message, true);
      mailSender.send(mailMessage);
    } catch (MessagingException e) {
      log.error("Failed to send mail: User:" + JSONObject.toJSONString(user) + ", Token: " + token);
    }
 
  }

Description: To send an email, two parameters, user and token, are passed in. user is the user registration information. token is a random UUID. redis has the corresponding key. its value is the user's json string.(The key rule is configuration file redis.prefix.signUp + UUID)

Mail Template Questions: Mail content is essentially a string whose style is controlled by html+css. When developed, templates are designed in the mailbox, variables are replaced by%s, and the entire string is stored in an appropriate place. When sending a message, the String.format() method is used to replace%s with the actual value, which results in the end user seeing the message.So there is no need to use third-party templates, adding jar packages can increase the complexity of the system, and the same functionality can be simplified as much as possible.

2. How to generate Token?See cn.ictgu.redis.RedisTokenManager

  public String getTokenOfSignUp(User user){
    String token = UUID.randomUUID().toString();
    String value = JSONObject.toJSONString(user);
    stringRedisTemplate.opsForValue().set(signUpPrefix + token, value);
    stringRedisTemplate.expire(signUpPrefix + token, 12, TimeUnit.HOURS);
    return token;
  }

Description: UUID.randomUUID().toString() is a method provided by javaJDK to automatically generate primary keys.UUID (Universal Unique Identifier) is a globally unique identifier, which is a number generated on a machine and guarantees that it is unique to all machines in the same space-time. It is composed of a 16-digit number and presented as a form.Combination of the following parts: Current date and time (the first part of a UUID is time dependent), if you generate another UUID a few seconds after a UUID is generated, the first part is different, the rest are the same), clock sequence, globally unique IEEE machine identification number (if there is a network card, obtained from the network card, not otherwise by the network card), unique flaw of the UUIDThe result string generated is longer.

3. With token, you need to associate user and token at the service level to send mail. Check out cn.ictgu.dao.service.UserService

  public boolean signUp(User user){
    String email = user.getEmail();
    if (existEmail(email)){
      log.error("User registration, mailbox registered:" + email);
      return false;
    }
    sendValidateEmail(user);
    return true;
  }

  @Async
  private void sendValidateEmail(User user){
    String token = tokenManager.getTokenOfSignUp(user);
    log.error("User registration, ready to send mail: User:" + JSONObject.toJSONString(user) + ", Token: " + token);
    mailService.userValidate(user, token);
  }

  private boolean existEmail(String email){
    return mapper.selectByEmail(email) != null;
  }

Description: Sending mail takes a long time, using asynchronous to improve user experience

4. user is simple

@RestController
public class UserApi {

  @Autowired
  private UserService userService;
  
  @RequestMapping(value = "/sign-up", method = RequestMethod.POST)
  public SimpleResponse signUp(HttpServletRequest request){
    User user = createUser(request);
    SimpleResponse response = checkSignUpRequest(user);
    if (response.getCode() == 100){
      if (!userService.signUp(user)){
        response.setCode(200);
        response.setMessage("This mailbox is already registered, do not re-register!");
        return response;
      }else {
        response.setMessage("Registration activation mail has been sent to your mailbox, please complete the registration within 12 hours of activation!");
        return response;
      }
    }
    return response;
  }
  
  private SimpleResponse checkSignUpRequest(User user){
    SimpleResponse response = new SimpleResponse();
    String email = user.getEmail();
    if (!CheckUtils.checkEmail(email)){
      response.setCode(200);
      response.setMessage("Illegal mailbox format");
      return response;
    }
    String password = user.getPassword();
    if (!CheckUtils.checkPassword(password)){
      response.setCode(200);
      response.setMessage("Password length must be 8-16 Bits, and must contain numbers and letters");
      return response;
    }
    String nickname = user.getNickname();
    if (!CheckUtils.checkNickname(nickname)){
      response.setCode(200);
      response.setMessage("Illegal nickname length");
      return response;
    }
    response.setCode(100);
    return response;
  }

}

Note: This layer mainly checks user registration parameters

review

From the bottom up, this is achieved from user registration to mail delivery, most of the code is parameter checking, because user behavior is not trusted, to build a secure background system, there is no dead end checking.

Github address

Address: https://github.com/ChinaSilence/any-video

Demo address:

Address: http://www.ictgu.cn

Related Articles

Spring Boot Full Stack Development: Chapter One Spring Boot Full Stack Development: Building Development Environment Spring Boot Full Stack Development: Application Deployment Usage Spring Boot Full Stack Development: Beautiful Mail Registration Spring Boot Full Stack Development: Parser Implementation Spring Boot Full Stack Development: Cool Video Resolution Spring Boot Full Stack Development: Video Analysis Enjoyment Spring Boot Full Stack Development: User Security Spring Boot Full Stack Development: Concurrent Crawler Optimization Not Ended to Continue

End-of-Text Benefits

Java material full link: https://pan.baidu.com/s/1pUCCPstPnlGDCljtBVUsXQ Password: b2xc More information: Selected Ali Java, Architecture, Micro Services, etc. in 2020, plus VInformation about: qwerdd111

This article is published by blog OpenWrite Release!

Tags: Programming Spring Redis log4j network

Posted on Fri, 06 Mar 2020 18:57:26 -0800 by ppowell