Spring-Boot- whole stack development: beautiful mail registration

Renderings

email registration

registration process

1. [distal] In the registration page the user to submit registration information; Parameter 2. [rear] submitted by the user verify, directly returns an error message is incorrect, correct execution downwardly; 3. [rear] randomly generates an ID, the ID as the key, the user information as a value, stored Redis, setting length; 4. [rear] generates an activation link to send e-mail through the mail system to the user's mailbox 5. [distal] FIG user clicks on the "registration confirmation"; 6 . [back-end] check value has expired, check whether the mailbox has been registered, no user information is saved to the database, it prompts the user has been registered;

Implementation (reverse analysis)

1, take a look at the mail sent to realize cn.ictgu.tools.mail.MailService

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;

/**
 * 邮件服务
 * 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 = "[邮件标题]";

  private static final String 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("发送邮件失败:User:" + JSONObject.toJSONString(user) + ", Token: " + token);
    }

  }
复制代码

Description: send a message need to pass two parameters and user token, user is the user registration information, token is a random UUID, redis have the corresponding key, its value is the user json string. (Key rule is that the configuration file redis.prefix.signUp + UUID)

Mail templates issue: the nature of the message content is a string, style html + css controlled by the development, design a good template in the mailbox, the variable% s in place, then the whole string will be stored in a suitable place, send e-mail when using String.format () method of the% s replaced by actual values, to generate the end user sees the message. So there is no need to use a third-party templates, add a jar package will increase the complexity of the system, the same function can be simplified as simple as possible.

2, Token how to generate it? 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 of automatically generating a primary key javaJDK provided. UUID (Universally Unique Identifier) ​​globally unique identifier, refers to numbers on a machine-generated, which ensures the same for all machines in the time and space are unique, is a sixteen-bit numbers, manifested form. The current date and time (UUID the first part of the time-related, then if you generate a UUID, a few seconds and generate a UUID, the first part of a different, remaining the same), the clock: a combination of the following parts of sequence, IEEE globally unique machine identification number (if any card, obtained from the card, the card is not otherwise obtained), the only drawback is that the results generated UUID string will be longer.

3, token there, we need to send a message in the service layer and the associated user token you, take a look at cn.ictgu.dao.service.UserService

  public boolean signUp(User user){
    String email = user.getEmail();
    if (existEmail(email)){
      log.error("用户注册,邮箱已注册:" + email);
      return false;
    }
    sendValidateEmail(user);
    return true;
  }

  @Async
  private void sendValidateEmail(User user){
    String token = tokenManager.getTokenOfSignUp(user);
    log.error("用户注册,准备发送邮件:User:" + JSONObject.toJSONString(user) + ", Token: " + token);
    mailService.userValidate(user, token);
  }

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

Description: send a message takes a long time, the use of asynchronous to do to improve the 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("此邮箱已注册,请勿重复注册!");
        return response;
      }else {
        response.setMessage("注册激活邮件已发送至您邮箱,请在12小时内激活完成注册!");
        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("邮箱格式不合法");
      return response;
    }
    String password = user.getPassword();
    if (!CheckUtils.checkPassword(password)){
      response.setCode(200);
      response.setMessage("密码长度必须为8-16位,且必须包含数字和字母");
      return response;
    }
    String nickname = user.getNickname();
    if (!CheckUtils.checkNickname(nickname)){
      response.setCode(200);
      response.setMessage("昵称长度不合法");
      return response;
    }
    response.setCode(100);
    return response;
  }

}复制代码

Description: This layer is mainly done to check user registration parameters

review

From the bottom up, from user registration to send e-mail on the realization that most of the code is to do parameter validation, because the user behavior is not credible, to build a secure back-end systems, will no dead checksum school experience. . . .

Github Address

Address: github.com/ChinaSilenc...

Demo Address:

Address: www.ictgu.cn

related articles

Spring Boot whole stack development: the beginning of Chapter Spring Boot whole stack development: development environment to build Spring Boot whole stack development: application deployment using Spring Boot whole stack development: beautiful mail registration Spring Boot whole stack development: parser implementation Spring Boot whole stack development : parsing the video Youku Spring Boot whole stack development: video parsing of music, as the Spring Boot whole stack development: user security Spring Boot whole stack development: optimization of concurrent reptiles to be continued

The end of the sentence welfare

Java Sourcebook link: pan.baidu.com/s/1pUCCPstP... Password: b2xc More Information: 2020 Featured Ali Java, architecture, micro-service selection information, etc., plus v ❤: qwerdd111

This article from the blog article multiple platforms OpenWrite release!

Guess you like

Origin juejin.im/post/5e6306fee51d4526ed66bfd9