业务点梳理:前后分离下的登录和注册----------------SpringCloud+Nuxt

一、后端API------restful风格

1、注册接口(发短信接口+插入用户信息并且校验的接口

注册没有什么特别的地方,和我以前用SSM,SpringBoot做的注册差不多

短信服务:https://www.cnblogs.com/mangoubiubiu/p/13973098.html

 

 

 用户中心:

 

 

 Controller

     //注册
    @PostMapping("register")
    public R register(@RequestBody RegisterVo registerVo){

         memberService.register(registerVo);

         return R.ok();
    }

Service

 public void register(RegisterVo registerVo) {

        //获取注册的code
        String  code =registerVo.getCode();
        String   mobile    =registerVo.getMobile();
        String   nickname   =registerVo.getNickname();
        String   pwd   =registerVo.getPassword();



        //非空判断
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(pwd) || StringUtils.isEmpty(code)  || StringUtils.isEmpty(nickname)){
            throw new GuiLiException(20001,"登录失败");
        }

        //判断code
        //从redis取验证码
        String redisCode=redisTemplate.opsForValue().get(mobile);

        if(!code.equals(redisCode)){
            throw new GuiLiException(20001,"注册失败");
        }

        //判断手机号是否重复
        QueryWrapper<UcenterMember> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("mobile",mobile);
        Integer count= baseMapper.selectCount(queryWrapper);
        //表示有相同
        if(count >0 ){
            throw new GuiLiException(20001,"注册失败");
        }

        UcenterMember member=new UcenterMember();
        member.setMobile(mobile);
        member.setNickname(nickname);
        member.setPassword(MD5.encrypt(pwd));
        member.setAvatar("");
        member.setIsDeleted(false);
        baseMapper.insert(member);


    }

2、登录接口(生成token--------解析token)

什么是登录,以前将用户信息存在session中,能从session中取到user信息就是登录,现在是看请求头中有无token

生成token:

controller

     //登录
      @PostMapping("login")
      public R login(@RequestBody UcenterMember ucenterMember){

          //调用service方法实现登录
          //返回token值 使用jwt生成
          String token= memberService.login(ucenterMember);


          return  R.ok().data("token",token);

      }

service:

@Override
    public String login(UcenterMember ucenterMember) {
        //获取登录手机号和密码
        String mobile=ucenterMember.getMobile();
        String pwd=ucenterMember.getPassword();

        //手机号和密码非空判断
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(pwd)){
            throw new GuiLiException(20001,"登录失败");
        }


        //判断手机号是否正确
        QueryWrapper<UcenterMember> queryWrapper=new QueryWrapper<>();

        queryWrapper.eq("mobile",mobile);
        //根据手机号查这个数据 是否存在
        UcenterMember mMember  = baseMapper.selectOne(queryWrapper);
        //判断查出来对象是否为空
        if(mMember==null){
            throw new GuiLiException(20001,"该用户不存在");
        }

        //判断密码是否正确
        //如果密码不正确
        //存到数据库里的密码是做了 MD5加密了的
        //所以用户输人的密码 先要进行加密在来和数据库里的比对
        if(!MD5.encrypt(pwd).equals(mMember.getPassword())){
            throw new GuiLiException(20001,"密码错误");
        }

        //判断用户是否被禁用
         if(mMember.getIsDisabled()){
             throw new GuiLiException(20001,"登录失败");
         }

         //登录成功
         //生成token字符串 使用工具类
        String jwtToken= JwtUtils.getJwtToken(mMember.getId(),mMember.getNickname());

         return jwtToken;
    }

JWT工具类:https://www.cnblogs.com/mangoubiubiu/p/13956626.html这里有

解析token

    //根据token获取用户信息
    @GetMapping("getMemberInfo")
    public R getMemberInfo(HttpServletRequest request){

        String menberId=JwtUtils.getMemberIdByJwtToken(request);
        //查询数据库 根据用户id获取用户信息
        UcenterMember member=    memberService.getById(menberId);
         return R.ok().data("member",member);
    }

 

二、前端页面调用

 

1、注册页面

定义调用api的js

import request from '@/utils/request'
export default {
  //根据手机号码发送短信
  getMobile(mobile){
    return request({
      url: `/edumsm/msm/send/${mobile}`,
      method: 'get'
    })
  },
  //用户注册
  submitRegister(formItem) {
    return request({
      url: `/educenter/ucenter-member/register`,
      method: 'post',
      data: formItem
    })
  }
}

这里的关键点有2个 

一个是用js的setInterval()方法实现倒计时

一个就是对用户输入的信息 进行聚焦事件,失去焦点事件校验

当然这里框架自己做好了 只需要照着写就完事了

 

<template>
  <div class="main">
    <div class="title">
      <a href="/login">登录</a>
      <span>·</span>
      <a class="active" href="/register">注册</a>
    </div>
    <div class="sign-up-container">
      <el-form ref="userForm" :model="params">
        <el-form-item class="input-prepend restyle" prop="nickname" :rules="[{ required: true, message: '请输入你的昵称', trigger: 'blur' }]">
          <div>
            <el-input type="text" placeholder="你的昵称" v-model="params.nickname"/>
            <i class="iconfont icon-user"/>
          </div>
        </el-form-item>
        <el-form-item class="input-prepend restyle no-radius" prop="mobile" :rules="[{ required: true, message: '请输入手机号码', trigger: 'blur' },{validator: checkPhone, trigger: 'blur'}]">
          <div>
            <el-input type="text" placeholder="手机号" v-model="params.mobile"/>
            <i class="iconfont icon-phone"/>
          </div>
        </el-form-item>
        <el-form-item class="input-prepend restyle no-radius" prop="code" :rules="[{ required: true, message: '请输入验证码', trigger: 'blur' }]">
          <div style="width: 100%;display: block;float: left;position: relative">
            <el-input type="text" placeholder="验证码" v-model="params.code"/>
            <i class="iconfont icon-phone"/>
          </div>
          <div class="btn" style="position:absolute;right: 0;top: 6px;width: 40%;">
            <a href="javascript:" type="button" @click="getCodeFun()" :value="codeTest" style="border: none;background-color: none">{{codeTest}}</a>
          </div>
        </el-form-item>
        <el-form-item class="input-prepend" prop="password" :rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]">
          <div>
            <el-input type="password" placeholder="设置密码" v-model="params.password"/>
            <i class="iconfont icon-password"/>
          </div>
        </el-form-item>
        <div class="btn">
       <input type="button" class="sign-up-button" value="注册" @click="submitRegister()">
        </div>
        <p class="sign-up-msg">
          点击 “注册” 即表示您同意并愿意遵守简书
          <br>
          <a target="_blank" href="http://www.jianshu.com/p/c44d171298ce">用户协议</a><a target="_blank" href="http://www.jianshu.com/p/2ov8x3">隐私政策</a></p>
      </el-form>
       <!-- 更多注册方式 -->
      <div class="more-sign">
        <h6>社交帐号直接注册</h6>
        <ul>
          <li><a id="weixin" class="weixin" target="_blank" href="http://huaan.free.idcfengye.com/api/ucenter/wx/login"><i
            class="iconfont icon-weixin"/></a></li>
          <li><a id="qq" class="qq" target="_blank" href="#"><i class="iconfont icon-qq"/></a></li>
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
  import '~/assets/css/sign.css'
  import '~/assets/css/iconfont.css'
  import registerApi from '@/api/register'

  export default {
    layout: 'sign',
    data() {
   return {
        params: {//封装注册输入的数据
          mobile: '',
          code: '',//验证码
        nickname: '',
          password: ''
        },
        sending: true,      //是否发送验证码
        second: 60,        //倒计时间
        codeTest: '获取验证码'
      }
    },
    methods: {
      
      //注册提交的方法
      submitRegister(){
        console.log(this.params)
          registerApi.submitRegister(this.params)
                     .then(response=>{

                    console.log(response.data.data)


                        //提示信息
                   this.$message({
                        type: 'success',
                        message: "注册成功"
                      })
                        //跳转到登录页面
              this.$router.push({path: '/login'})
                 

                     })
      },

      //通过输入的手机号调接口
      getCodeFun(){ 
         registerApi.getMobile(this.params.mobile)
                    .then(response=>{
                      this.sending=false
                       //提示信息
                      this.$message({
                        type: 'success',
                        message: "短信发送成功请注意查收"
                      })
                      //倒计时
                      this.timeDown()
                    })
      },
      timeDown() {
        let result = setInterval(() => {
          --this.second;
          this.codeTest = this.second
          if (this.second < 1) {
            clearInterval(result);
            this.sending = true;
            //this.disabled = false;
            this.second = 60;
            this.codeTest = "获取验证码"
          }
        }, 1000);
      },
      checkPhone(rule, value, callback) {
        if (!(/^1[34578]\d{9}$/.test(value))) {
          return callback(new Error('手机号码格式不正确'))
        }
        return callback()
      }
  
  }
  }
</script>

2、登录页面

下载js-cookie插件
npm install js-cookie

api

import request from '@/utils/request'
export default {
  //根据token值获取用户信息
  getLoginUserInfo(){
    return request({
      url: `/educenter/ucenter-member/getMemberInfo`,
      method: 'get'
    })
  },
  //登录
  submitLogin(userInfo) {
    return request({
      url: `/educenter/ucenter-member/login`,
      method: 'post',
      data: userInfo
    })
  }
}

这里的关键点  是先要将登录后从后端返回的token信息 存到cookie里面,然后加一个请求拦截,看cookie里是否有token 有拦截所有的axios请求 并在请求的后面带上token信息

,然后需要再请求后端解析token 返回用户信息存cookie里面 以便于前端页面进行数据展示

<template>
  <div class="main">
    <div class="title">
      <a class="active" href="/login">登录</a>
      <span>·</span>
      <a href="/register">注册</a>
    </div>
    <div class="sign-up-container">
      <el-form ref="userForm" :model="user">
        <el-form-item class="input-prepend restyle" prop="mobile" :rules="[{ required: true, message: '请输入手机号码', trigger: 'blur' },{validator: checkPhone, trigger: 'blur'}]">
          <div >
            <el-input type="text" placeholder="手机号" v-model="user.mobile"/>
            <i class="iconfont icon-phone" />
          </div>
        </el-form-item>
        <el-form-item class="input-prepend" prop="password" :rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]">
          <div>
            <el-input type="password" placeholder="密码" v-model="user.password"/>
           <i class="iconfont icon-password"/>
          </div>
        </el-form-item>
        <div class="btn">
          <input type="button" class="sign-in-button" value="登录" @click="submitLogin()">
        </div>
      </el-form>
      <!-- 更多登录方式 -->
      <div class="more-sign">
        <h6>社交帐号登录</h6>
        <ul>
           <li><a id="weixin" class="weixin" target="_blank" href="http://qy.free.idcfengye.com/api/ucenter/weixinLogin/login"><i class="iconfont icon-weixin"/></a></li>
          <li><a id="qq" class="qq" target="_blank" href="#"><i class="iconfont icon-qq"/></a></li>
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
  import '~/assets/css/sign.css'
  import '~/assets/css/iconfont.css'
   import cookie from 'js-cookie'
  import loginApi from '@/api/login'
  export default {
    layout: 'sign',
    data () {
      return {
        user:{
          mobile:'',
          password:''
        },
        loginInfo:{}
      }
    },
    methods: {
          submitLogin(){
           loginApi.submitLogin(this.user)
                   .then(response=>{
                     //获取token
                    //将用户信息记录cookie
                   cookie.set('guli_token',response.data.data.token, { domain: 'localhost' })
                   //获取用户信息
                   loginApi.getLoginUserInfo()
                           .then(response=>{
                          this.loginInfo = response.data.data.member
                             //获取返回的用户信息,放到cookie中
                          cookie.set('guli_ucenter', this.loginInfo, { domain: 'localhost' })
                          //跳转页面
                         window.location.href = "/";
                           })
                   })
            
          },
           checkPhone(rule, value, callback) {
        if (!(/^1[34578]\d{9}$/.test(value))) {
          return callback(new Error('手机号码格式不正确'))
        }
        return callback()
      }
    }
  }
</script>
<style>
   .el-form-item__error{
    z-index: 9999999;
  }
</style>

修改request.js

 

 

 

import axios from 'axios'
//import { MessageBox, Message } from 'element-ui'
import cookie from 'js-cookie'
// 创建axios实例
const service = axios.create({
   //baseURL: 'http://qy.free.idcfengye.com/api', // api 的 base_url
  //baseURL: 'http://localhost:8210', // api 的 base_url
  baseURL: 'http://localhost:9001',
  timeout: 15000 // 请求超时时间
  
})
// http request 拦截器
service.interceptors.request.use(
  config => {
  //debugger
  //判断cookie里是否有值
  if (cookie.get('guli_token')) {
    config.headers['token'] = cookie.get('guli_token');
  }
    return config
  },
  err => {
  return Promise.reject(err);
})
/*
// http response 拦截器
service.interceptors.response.use(
  response => {
    //debugger
    if (response.data.code == 28004) {
        console.log("response.data.resultCode是28004")
        // 返回 错误代码-1 清除ticket信息并跳转到登录页面
        //debugger
        window.location.href="/login"
        return
    }else{
      if (response.data.code !== 20000) {
        //25000:订单支付中,不做任何提示
        if(response.data.code != 25000) {
          Message({
            message: response.data.message || 'error',
            type: 'error',
            duration: 5 * 1000
          })
        }
      } else {
        return response;
      }
    }
  },
  error => {
    return Promise.reject(error.response)   // 返回接口返回的错误信息
});*/
export default service

 

posted @ 2020-11-21 16:36  KwFruit  阅读(276)  评论(0编辑  收藏  举报