在线教育项目用户登录和注册(二)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 在线教育项目用户登录和注册

3. 用户登录

  • element ui admin 执行流程图

image.png

3.0 取消登录表单校验

image.png

3.1 发送验证码邮件

image.png

3.1.1 前端:显示表单

  • 登录页面:@/views/login/index.vue

image.png

<!-- 邮箱 -->
      <el-form-item prop="email">
        <span class="svg-container">
          <svg-icon icon-class="email" />
        </span>
        <el-input
          ref="email"
          v-model="loginForm.email"
          placeholder="请输入邮箱"
          name="email"
          type="text"
          tabindex="3"
          style="width:70%;"
        />
        <el-button  type="primary" style="width:20%" @click.native.prevent="sendEmail">发送</el-button>
      </el-form-item>
      <!-- 验证码 -->
      <el-form-item prop="verifycode">
        <span class="svg-container">
          <svg-icon icon-class="guide" />
        </span>
        <el-input
          ref="verifycode"
          v-model="loginForm.verifycode"
          placeholder="请输入验证码"
          name="verifycode"
          type="text"
          tabindex="4"
        />
      </el-form-item>

3.1.2 前端:发送邮件

  • 编写API,发送邮件

image.png

export function send(user) {
  return axios.post('/user-service/user/sendemail',user);
}
  • 调用

image.png

    async sendEmail() {
      let { message } = await send( this.loginForm)
      this.$message.success( message )
    }

3.1.3 完善 EduUser

  • 用于封装表单提交的用户数据
package com.czxy.zx.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Date;
/**
 *
 */
@Data
//@TableName("edu_user")
@ApiModel(value = "EduUser对象",description = "用户")
public class EduUser {
    @TableId(value="id" , type = IdType.AUTO)
    private Integer id;
    //用户名
    private String username;
    //用户密码
    private String password;
    //电话
    private String phone;
    //邮箱
    private String email;
    //角色,多个值使用逗号分隔,例如:admin,editor
    private String roles;
    //创建时间
    private Date created;
    //状态:0 未激活、1已激活
    private String status;
    @TableField(exist = false)
    private String verifycode;
}

3.1.4 用于封装与MQ交互的数据

image.png

package com.czxy.zx.vo; import lombok.Data; /** * @author 桐叔 * @email liangtong@itcast.cn */ @Data public class UserEmail { private String username; private String email; private String text; }

3.1.5 编写Rabbit配置类

image.png

package com.czxy.zx.user.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
public class RabbitEmailConfig {
    // 队列的名称
    public static final String QUEUE_NAME = "zx-email";
    @Bean
    public Queue queue() {
        return new Queue(QUEUE_NAME);
    }
}

3.1.6 后端实现

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/user")
public class EduUserController {
    @Resource
    private EduUserService eduUserService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @PostMapping("/sendemail")
    public BaseResult sendemail(@RequestBody EduUser eduUser) {
        //1 随机字符串
        Random random = new Random();
        // [0,8999) --> [1000,9999)
        int randomNumber = random.nextInt(8999) + 1000;
        //2 发送redis一份
        stringRedisTemplate.opsForValue().set("login" + eduUser.getUsername(), randomNumber + "");
        //3 mq存放
        UserEmail userEmail = new UserEmail();
        userEmail.setUsername(eduUser.getUsername());
        userEmail.setEmail(eduUser.getEmail());
        userEmail.setText("登录验证码是:" + randomNumber);
        String userEmailStr = JSONObject.toJSONString(userEmail);
        rabbitTemplate.convertAndSend(RabbitEmailConfig.QUEUE_NAME , userEmailStr);
        return BaseResult.ok("发送中,请查收");
    }

3.2 编写MQ:发送邮件

image.png

3.2.1 拷贝配置类

  • 与登录模块使用的配置类相同

image.png

package com.czxy.zx.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
public class RabbitEmailConfig {
    // 队列的名称
    public static final String QUEUE_NAME = "zx-email";
    @Bean
    public Queue queue() {
        return new Queue(QUEUE_NAME);
    }
}

3.2.2 监听器发送邮件

image.png

package com.czxy.zx.listener;
import com.alibaba.fastjson.JSONObject;
import com.czxy.zx.config.RabbitEmailConfig;
import com.czxy.zx.utils.EmailUtils;
import com.czxy.zx.vo.UserEmail;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
public class RabbitEmailListener {
    @Resource
    private JavaMailSender javaMailSender;
    @RabbitListener(queues = RabbitEmailConfig.QUEUE_NAME)
    public void sendEmail(String message) {
        //1 将消息转换成 UserEmail
        UserEmail userEmail = JSONObject.parseObject(message, UserEmail.class);
        //2 发送邮件,如果邮箱为空,将出现循环异常
       if(userEmail.getEmail() != null) { EmailUtils.sendEmail(javaMailSender,userEmail.getEmail(),userEmail.getText());
       }
    }
}

3.3 后端:用户登录

3.3.0 前端登录流程

  • 步骤一:登录页面 @/views/login/index.vue

image.png

步骤二:登录调用 vuex

image.png

步骤三:查看vuex

image.png

步骤四:调用ajax

image.png

  • 步骤五:确定ajax发送位置

image.png

3.3.1 修改前端api

export function login(user) {
  // 真实数据
  return axios.post('/user-service/user/login',user);
  // 临时模拟
  // return axios.post('/teacher-service/user/login',user);
}

3.3.2 修改前端请求数据

image.png

3.3.2 后端实现

  • EduUserController 添加 login 方法
package com.czxy.zx.user.controller;
import com.alibaba.fastjson.JSON;
import com.czxy.zx.domain.EduUser;
import com.czxy.zx.user.config.RabbitEmailConfig;
import com.czxy.zx.user.service.EduUserService;
import com.czxy.zx.vo.BaseResult;
import com.czxy.zx.vo.UserEmail;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/user")
public class EduUserController {
    @Resource
    private EduUserService eduUserService;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @PostMapping("/send")
    public BaseResult send(@RequestBody EduUser eduUser) {
        //1 随机生成验证码
        int num = RandomUtils.nextInt(1000, 10000);
        //2 封装发送邮件的数据--
        UserEmail userEmail = new UserEmail();
        userEmail.setEmail(eduUser.getEmail());
        userEmail.setTitle("用户登录验证码");
        userEmail.setText(eduUser.getUsername() + "您好,本次验证码:" + num);
        //3 发送邮件-将邮件信息存放mq
        String jsonStr = JSON.toJSONString(userEmail);
        rabbitTemplate.convertAndSend("", RabbitEmailConfig.QUEUE_NAME, jsonStr);
        //4 将验证码存放redis
        String redisName = "login_verify_code_" + eduUser.getUsername();
        stringRedisTemplate.opsForValue().set(redisName, num + "");
        //5 提示
        return BaseResult.ok("验证码发送成功!");
    }
    @PostMapping("/login")
    public BaseResult login(@RequestBody EduUser eduUser) {
        //1 校验验证码
        // 1.1 获得redis
        String redisName = "login_verify_code_" + eduUser.getUsername();
        String redisVerifyCode = stringRedisTemplate.opsForValue().get(redisName);
        // 1.2 删除redis
        stringRedisTemplate.delete(redisName);
        // 1.3 校验:无效
        if(redisVerifyCode == null) {
            return BaseResult.error("验证码无效");
        }
        // 1.4 校验:错误
        if(!redisVerifyCode.equalsIgnoreCase(eduUser.getVerifycode())) {
            return BaseResult.error("验证码错误");
        }
        //2 通过service用户登录
        EduUser loginUser = eduUserService.login(eduUser);
        //3 提示
        if(loginUser != null) {
            // 需要设置token
            String token = "admin-token";
            return BaseResult.ok("登录成功").append("token", token);
        }
        return BaseResult.error("用户名或密码不匹配");
    }
}

3.3.4 前端修改

image.png

3.3.5 数据要求 admin-token

image.png

登录成功后,查询用户详情的使用

image.png

3.4 登录成功后查询权限

3.4.1 分析

  • 登录时,返回一个固定的字符串:admin-token 或 editor-token
  • 登录成功后,查询用户详情将携带固定字符串

image.png

根据固定字符串查询用户的权限,并返回固定的信息:

{
  roles: ['admin'],       //用户角色 或 [editor] 或 [admin,editor]
  avatar: '',           //头像图片地址
  name: '',           //用户名
}

image.png

查询详情ajax调用时机

image.png

3.4.2 前端完善

image.png

3.4.3 后端实现

  • 完善 EduUserController,添加查询详情功能
/**
     * 查询详情
     * @param token
     * @return
     */
    @GetMapping("/info")
    public BaseResult info(String token) {
        System.out.println(token);
        Map<String,Object> map = new HashMap<>();
        // 根据固定字符串拼凑数据
        if("admin-token".equals(token)) {
            map.put("roles", Arrays.asList("admin"));
            map.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
            map.put("name","Super Admin");
        } else {
            map.put("roles", Arrays.asList("editor"));
            map.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
            map.put("name","Normal Editor");
        }
        return BaseResult.ok("成功", map);
    }


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
7月前
|
Web App开发 移动开发 前端开发
前端企业微信服务商第三方应用开发详情流程
前端企业微信服务商第三方应用开发详情流程
299 0
|
5月前
|
小程序 前端开发 安全
微信小程序OA会议系统个人中心授权登入
微信小程序OA会议系统个人中心授权登入
42 0
|
5月前
|
JSON 前端开发 NoSQL
淘东电商项目(27) -门户登出功能
淘东电商项目(27) -门户登出功能
26 0
|
7月前
|
XML 缓存 NoSQL
手把手实现第三方社交登录方式微信登录
手把手实现第三方社交登录方式微信登录
95 0
|
8月前
|
SQL 缓存 前端开发
用户登录【项目 商城】
用户登录【项目 商城】
103 0
|
8月前
|
存储 小程序 数据库
云开发(微信-小程序)笔记(十三)---- 注册登陆
云开发(微信-小程序)笔记(十三)---- 注册登陆
81 0
云开发(微信-小程序)笔记(十三)---- 注册登陆
|
JavaScript Java 数据库
企业微信接入系列-扫码绑定/登录
讲述在企业后台管理平台账号绑定企业微信以及企业微信扫码登录企业管理平台
企业微信接入系列-扫码绑定/登录
|
11月前
|
JSON JavaScript 前端开发
前后端分离项目知识汇总(整合短信登录和微信扫描登录)
前后端分离项目知识汇总(整合短信登录和微信扫描登录)
151 0
|
数据安全/隐私保护
阿里云国际版账户简便注册流程
如需注册阿里云国际版账号,可以与alicloudlx联系,只需要一个邮箱就ok了,简单快捷
阿里云国际版账户简便注册流程
|
XML 安全 Java
微信服务(公众)号实现用户关注自动注册成为会员
微信服务(公众)号实现用户关注自动注册成为会员
117 0