註冊流程
【1】前端提交註冊信息
【2】後端接受數據
【3】後端生成一個UUID作爲token,將token做爲redis的key值,用戶數據做爲redis的value值,並設置key的時長
【4】後端根據用戶信息中的郵箱地址信息,檢驗用戶是否已經註冊,若是沒有,生成註冊連接發送到用戶郵箱,若是已經註冊,提示用戶該郵箱地址已被註冊
【5】用戶點擊郵件中的註冊連接
【6】後端判斷redis中token是否過時,沒有將用戶信息保存到數據庫,提示用戶註冊成功
項目源碼:https://gitee.com/residual-temperature/email-link-demo.git
郵箱效果圖
html
一、pom文件要加入的jar包前端
<!-- 郵件相關 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!-- redis相關 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
二、application.yml文件中要加入的配置java
spring: redis: host: # redis地址 port: 6379 # redis端口號(默認6379) password: # redis密碼 mail: host: smtp.qq.com # 郵箱協議 username: 地址 # 發送的郵箱地址 password: 受權碼 # 郵箱的受權碼
三、定義實體類git
@Repository @Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private long id; private String account; private String password; private String username; }
注意redis
此處沒有get(),set()方法是由於導入了lombok包spring
四、redis的config配置
對象的保存須要序列化,因此須要自定義RedisTempletesql
@Configuration public class RedisConfig { //編寫本身的配置類 @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { //爲了開發方便通常使用<String,Object> RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); //JSON序列化的配置 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //String的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); //key採用String的序列化方式 template.setKeySerializer(stringRedisSerializer); //hash採用String的序列方式 template.setHashKeySerializer(stringRedisSerializer); //value序列化採用jackson template.setValueSerializer(jackson2JsonRedisSerializer); //hash的Value序列化採用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
五、驗證連接生成和郵箱發送的工具類CodeUtils的配置數據庫
@Component public class CodeUtils { @Resource JavaMailSender mailSender; @Resource RedisTemplate<String, User> redisTemplate; // 生成連接,並給接收的郵箱發送郵件 public boolean sendCode(User user){ MimeMessage message = mailSender.createMimeMessage(); try{ MimeMessageHelper messageHelper = new MimeMessageHelper(message); String token = UUID.randomUUID().toString(); // 生成UUID redisTemplate.opsForValue().set(token,user); redisTemplate.expire(token,300, TimeUnit.SECONDS); messageHelper.setFrom("發送方的郵箱地址"); //發送方的郵箱地址,而不是接收方的郵箱地址 messageHelper.setTo(user.getAddress()); // 接收方的郵箱地址 messageHelper.setSubject("註冊"); // 郵箱標題 String html = "<html>\n" + "<body>\n" + "<p>請點擊下方連接註冊</p>\n" + "<a href=\"http://localhost:8081/lookCode/"+token+"\">http://localhost:8081/lookCode/"+token+"</a>" + "</body>\n" + "</html>"; messageHelper.setText(html,true); // 郵箱內容 mailSender.send(message); // 發送郵箱 System.out.println("發送成功"); return true; }catch (Exception e){ System.out.println("發送失敗"); return false; } } // 判斷token是否過時 public boolean eqToken(String token){ return redisTemplate.hasKey(token); } // 根據token查詢用戶的信息 public User findUser(String token){ return redisTemplate.opsForValue().get(token); } }
六、UserMapper的配置後端
@Mapper @Repository public interface UserMapper { // 添加用戶 註解開發sql語句 @Insert("insert into user(account,password,username) values (#{account},#{password},#{username})") public int addUser(User user); }
七、UserService的配置網絡
public interface UserService { // 添加用戶 public boolean adduser(User user); // 根據用戶註冊信息進行註冊連接的的生成和發送 public boolean sendCode(User user); // 用戶點擊註冊連接判斷token是否過時 public boolean eqToken(String token); }
八、UserService的實現類UserServiceImpl的配置
@Service public class UserServiceImpl implements UserService { @Resource UserMapper userMapper; @Resource CodeUtils codeUtils; /** * 添加註冊的用戶信息 * @param user 註冊的用戶信息 * @return 是否添加成功 */ @Override public boolean adduser(User user) { return userMapper.addUser(user) > 0; } /** * 生成連接和發送連接 * @param address 接收的郵箱地址 * @param user 註冊的用戶信息 */ @Override public boolean sendCode(User user) { if ( codeUtils.sendCode(user)) // 調用驗證連接生成工具類中的生成連接和發送郵件函數 return true; else return false; } /** * 判斷token是否過時 * @param token 用戶註冊所接收的token * @return 註冊成功與否 */ @Override public boolean eqToken(String token) { boolean flag = codeUtils.eqToken(token); if (flag){ User user = codeUtils.findUser(token); adduser(user); return true; }else { return false; } } }
九、UserController的配置
@RestController public class UserController { @Resource UserService userService; // 根據用戶註冊信息進行註冊連接的的生成和發送 @PostMapping("/sendCode") public Map<String,String> sendCode(@RequestBody User user){ boolean flag = userService.sendCode(user); Map<String,String> map = new HashMap<>(); if (flag){ map.put("msg","郵件發送成功,請前往您的郵箱進行註冊驗證"); return map; }else { map.put("msg","郵件發送失敗"); return map; } } // 判斷是否註冊成功 @GetMapping("/lookCode/{token}") public Map<String,String> lookCode(@PathVariable("token")String token){ boolean flag = userService.eqToken(token); Map<String,String> map = new HashMap<>(); if (flag){ map.put("msg","註冊成功"); /* 後續的操做 ... ...*/ return map; }else { map.put("msg","註冊碼過時,請從新註冊"); return map; } } }
由於沒有寫前端頁面,因此就用postman和頁面來演示
傳入user對象
返回結果
郵箱連接
點擊註冊連接以後
註冊成功以後數據庫先後對比
註冊成功以前
註冊成功以後
可能會遇到的問題 【1】有些內部網絡不支持發送郵箱,若是保證代碼沒錯,能夠換個網絡試試 【2】若是是在本地測試,鏈接的是本地redis,記得開啓本地的redis