登录注册接口完善

登录注册接口实现

后端

import re
from rest_framework.views import APIView
from utils.response import APIResponse
from utils.auth import cache_token,clear_token,need_token
from libs.ali_sms import get_code
from django.core.cache import cache

# Create your views here.
from .throttles import SMSThrottle
from . import serializers
from . import models


class SMSAPIView(APIView):
    throttle_classes = [SMSThrottle]
    def post(self,request,*args,**kwargs):

        mobile = request.data.get('mobile')
        if not mobile or not re.match(r'^1[3-9][0-9]{9}$', mobile):
            return APIResponse(1, '手机号有误')

        # 产生验证码
        code = get_code()

        # 通知第三方发送短信
        # result = send_sms(mobile,code)
        # 失败:
        # if not result:
        #     return APIResponse(1,'短信发送失败')
        # 成功设置到redis数据库里面:
        print(code)
        cache.set(f'{mobile}_code',code,5*60)
        # print(cache.get(f'{mobile}_code'))
        return APIResponse(0,'短信发送成功')



class MobileAPIView(APIView):
    def get(self,request,*args,**kwargs):
        # 获取手机号
        mobile = request.query_params.get('mobile')
        if not mobile:
            return APIResponse(1,'手机号必须提供')
        # 校验手机号是否合法
        if not re.match(r'^1[3-9][0-9]{9}$',mobile):
            return APIResponse(1,'手机号有误')
        try:
            models.User.objects.get(mobile=mobile, is_active=True)
            return APIResponse(1,'手机已注册')
        except:
            return APIResponse(0,'手机号未注册')


class RegisterAPIView(APIView):
    def post(self,request,*args,**kwargs):
        # user_ser = serializers.
        # 校验
        user_ser = serializers.UserModelSerializer(data=request.data)
        if user_ser.is_valid():
            user_ser.save()
            return APIResponse(0,'注册成功',results=user_ser.data)
        else:
            # print(user_ser.errors)
            # res = user_ser.errors.values()
            # print(res)
            # print()
            return APIResponse(1,'注册失败',results=list(user_ser.errors.values())[0][0])

# 登录功能
from rest_framework_jwt.serializers import jwt_encode_handler ,jwt_payload_handler
class LoginAPIView(APIView):
    authentication_classes = ()
    permission_classes = ()
    def post(self,request,*atgs,**kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        code = request.data.get('code')
        is_remeber = request.data.get('is_remeber')

        if password and username:
            if re.match(r'^1[3-9][0-9]{9}$', username):
                try:
                    # 手动通过 user 签发 jwt-token
                    user = models.User.objects.get(mobile=username)
                except:
                    return APIResponse(1, '该手机未注册')
            else:
                # 因为不是纯数字所以也就不包括手机号码,不包括手机号码就一定是用户名
                if re.match(r'^/d*$', username):
                    return APIResponse(1,'用户名不能为纯数字')
                try:
                    user = models.User.objects.get(username=username)
                    if not user.check_password(password):
                        return APIResponse(1,'密码错误')
                except:
                    return APIResponse(1,'该账号未注册')
            # 签发token
            # payload = jwt_payload_handler(user)
            # token = jwt_encode_handler(payload)
            token = cache_token(request,user.id, user.password,is_remeber)
            return APIResponse(0, 'ok', results={
                'username': user.username,
                'mobile': user.mobile,
                'token': token
            })
        if username and code:
            if not re.match(r'^1[3-9][0-9]{9}$', username):
                return APIResponse(1,'手机号格式错误')

            cache_code = cache.get(f'{username}_code')
            cache.delete(f'{username}_code')
            if code!= cache_code:
                return APIResponse(1,'验证码错误')
            try:
                # 手动通过 user 签发 jwt-token
                user = models.User.objects.get(mobile=username)
            except:
                return APIResponse(1, '该手机未注册')
            # 签发token
            # payload = jwt_payload_handler(user)
            # token = jwt_encode_handler(payload)
            token = cache_token(request, user.id, user.password, is_remeber)
            return APIResponse(0, 'ok', results={
                'username': user.username,
                'mobile': user.mobile,
                'token': token
            })
        return APIResponse(1,'参数不全')

前端(修订Login和Register和Header)

Register

<template>
    <div class="box">
        <img src="@/assets/img/Loginbg.jpg" alt="">
        <div class="register">
            <div class="register_box">
                <div class="register-title">注册路飞学城</div>
                <div class="inp">

                    <input v-model="username" @blur="checkUser" type="text" placeholder="用户名" :class="{user:true,error:username_ver}">
                    <input v-model="mobile" @blur="checkMobile" type="text" placeholder="手机号码" :class="{user:true,error:mobile_ver}">
                    <input v-model="password" @blur="checkpassword" type="password" placeholder="用户密码" :class="{user:true,error:password_ver}">
                    <input v-model="repassword" @blur="checkrepassword" type="password" placeholder="再次输入用户密码" :class="{user:true,error:repassword_ver}">
                    <div class="sms">
                        <input v-model="sms" type="text" placeholder="输入验证码" class="user">
                        <span class="sms_btn" @click="send_sms">{{sms_interval_tips}}</span>
                    </div>
                    <div id="geetest"></div>
                    <button class="register_btn" @click="registerMobile">注册</button>
                    <p class="go_login">已有账号
                        <router-link to="/login">直接登录</router-link>
                    </p>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'Register',
        data() {
            return {
                username:"",
                sms: "",
                mobile: "",
                password: "",
                repassword: "",
                username_ver:false,
                sms_ver: false,
                mobile_ver: false,
                password_ver: false,
                repassword_ver: false,
                is_send: false,  // 是否在60s内发送了短信
                sms_interval_tips: "获取验证码",
            }
        },
        created() {
             console.log(/^[0-9a-zA-Z.]{6,16}$/.test('zmss y.'));
        },
        methods: {
            // 校验用户名长度
            checkUser(){
                if (this.username.length>15){
                    this.$message({
                        message:'用户名长度不能超过15个字符',
                        type:'error'
                    });
                    this.username_ver = true

                }else {
                    this.username_ver =false

                }
                if (/^\d*$/.test(this.username)){
                    this.$message({
                        message:'用户名不能为纯字数字',
                        type:'error'
                    });
                    this.username_ver = true

                }else {
                    this.username_ver =false

                }
            },
            checkpassword(){
                if (!/^[0-9a-zA-Z.]{6,16}$/.test(this.password)){
                    // this.username='';
                    this.$message({
                        message:'密码只能由 /数字/字母/点/ 组成',
                        type:'error'
                    });
                    this.password_ver =true
                }else{

                this.password_ver = false
                }

            },
            checkrepassword(){
                if (this.password !== this.repassword){
                    this.$message({
                        message:'两次密码不一致',
                        type:'error'
                    });
                    this.repassword_ver=true
                }else{
                this.repassword_ver = false

                }

            },
            // 电话号失去焦点会触发这个。
            checkMobile() {

                if (this.mobile.length < 1) {
                    return false;
                }

                // 手机号码格式是否正确
                if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
                    this.$message({
                        message: "对不起!手机号码格式有误!"
                    });
                    this.mobile_ver=true;
                    return false;
                }

                // 验证手机号码是否已经注册了
                // this.$axios.get(this.$settings.Host+"/users/mobile/"+this.mobile+"/");
                this.$axios({
                    url: this.$settings.base_url + '/user/mobile/',
                    method: 'get',
                    params: {
                        mobile: this.mobile
                    }
                }).then(response => {
                    let data = response.data;
                    window.console.log(data);
                    if (data.status != 0) {
                        this.$message({
                            message: "对不起!手机号码已经被注册!"
                        });
                        this.mobile_ver = true;
                        return false;
                    } else {
                        this.$message({
                            message: "期待您加入我们!"
                        });
                        this.mobile_ver = false
                    }
                }).catch(error => {
                    let data = error.response.data;
                    this.$message({
                        message: data.message
                    })
                })

            },
            // 发送验证码
            send_sms() {
                if (this.mobile.length < 1) {
                    this.$message({
                        message: "请填写手机号"
                    });
                    return false;
                }
                // 发送短信
                if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
                    this.$message({
                        message: "对不起!手机号码格式有误!"
                    });

                    return false;
                }

                // 判断是否在60s内发送过短信
                if (this.is_send) {
                    this.$message({
                        message: "对不起,不能频繁发送短信验证!"
                    });

                    return false;
                }

                // 请求发送短信
                this.$axios({
                    url: this.$settings.base_url + '/user/sms/',
                    method: 'post',
                    data: {
                        mobile: this.mobile
                    }
                }).then(response => {
                    this.$message({
                        message: response.data.msg,
                        type:'success'
                    });
                    // 修改短信的发送状态
                    this.is_send = true;

                    // 设置间隔时间60s
                    let sms_interval_time = 60;
                    // 设置短信发送间隔倒计时,.60s后把is_send改成false
                    let timer = setInterval(() => {
                        if (sms_interval_time <= 1) {
                            clearInterval(timer);
                            this.sms_interval_tips = "获取验证码";
                            this.is_send = false; // 重新恢复点击发送功能的条件
                        } else {
                            sms_interval_time -= 1;
                            this.sms_interval_tips = `${sms_interval_time}秒后再次获取`;
                        }
                    }, 1000);

                }).catch(error => {
                    this.$message({
                        message: error.response.data.result,
                    })
                });

            },
            // 注册
            registerMobile() {
                if (this.username.length<1){
                    this.$message({
                        message:'请填写用户名',
                        type:'error'
                    });
                    return false;
                }
                if (this.username.length>15){
                    this.$message({
                        message:'用户名长度不能超过15个字符',
                        type:'error'
                    });
                    this.$router.push('/login');
                    return false;
                }
                if (/^\d*$/.test(this.username)){
                    this.$message({
                        message:'用户名不能为纯字数字',
                        type:'error'
                    });
                    this.username_ver = true
                    return false

                }else {
                    this.username_ver =false

                }



                // 注册信息提交
                if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
                    this.$message({
                        message: "对不起!手机号码格式有误!"
                    });

                    return false;
                }

                if (this.sms.length < 1) {
                    this.$message({
                        message: "短信验证码不能为空!"
                    });

                    return false;
                }

                if (this.password.length < 6 || this.password.length > 16) {
                    this.$message({
                        message: "对不起,密码长度必须在6-16个字符之间!"
                    });

                    return false;
                }

                this.$axios({
                    url: this.$settings.base_url + '/user/register/mobile/',
                    method: 'post',
                    data: {
                        username:this.username,
                        mobile: this.mobile,
                        password: this.password,
                        repassword: this.repassword,
                        code: this.sms
                    }
                }).then(response => {
                    // let _this = this;

                    let status = response.data.status;
                    // let msg = response.data.msg;
                    if (status == 0){
                        this.username='';
                        this.mobile = '';
                        this.password='';
                        this.repassword='';
                        this.code = '';
                        this.$message({
                            message:'注册成功!!!',
                            duration:2000,
                            type:'success',
                            onClose:()=>{
                                this.$router.push('/login')
                            }
                        })
                    }else{
                        // this.mobile = '';
                        // this.password = '';
                        // this.sms =response.result.;
                        //     message:response.data.results,
                        // console.log(response.data.results)
                        // console.log(response.data.results[0][0])
                        this.$message({
                            message:response.data.results,
                            duration:1000,
                        })
                    }


                }).catch(error => {
                    this.$message({
                        message: error
                    });
                })

            }
        },

    };
</script>

Login.vue

<template>
    <div class="login box">
        <img src="@/assets/img/Loginbg.jpg" alt="">
        <div class="login">
            <div class="login-title">
                <img src="@/assets/img/Logotitle.png" alt="">
                <p>帮助有志向的年轻人通过努力学习获得体面的工作和生活!</p>
            </div>
            <div class="login_box">
                <div class="title">
                    <span :class="{active: a0}" @click="changeLogin(0)">密码登录</span>
                    <span :class="{active: a1}" @click="changeLogin(1)">短信登录</span>
                </div>
                <div class="inp" v-if="login_type==0">
                    <input v-model="username" type="text" placeholder="用户名 / 手机号码" class="user">
                    <input v-model="password" type="password" name="" class="pwd" placeholder="密码">
                    <div id="geetest1"></div>
                    <div class="rember">
                        <p>
                            <input id="checkbox" type="checkbox" class="no" v-model="remember"/>
                            <span>记住密码</span>
                        </p>
                        <p>忘记密码</p>
                    </div>
                    <button class="login_btn" @click="loginAction">登录</button>
                    <p class="go_login">没有账号
                        <router-link to="/register">立即注册</router-link>
                    </p>
                </div>
                <div class="inp" v-show="login_type==1">
                    <input v-model="mobile" type="text" placeholder="手机号码" class="user">
                    <div class="sms">
                        <input v-model="sms" type="text" placeholder="输入验证码" class="user">
                        <span class="sms_btn" @click="send_sms">{{sms_interval_tips}}</span>
                    </div>
                    <button class="login_btn" @click="loginMobile">登录</button>
                    <p class="go_login">没有账号
                        <router-link to="/register">立即注册</router-link>
                    </p>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'Login',
        data() {
            return {
                a0: 1,
                a1: 0,
                login_type: 0,
                username: "",
                password: "",
                remember: false,
                mobile: "",
                sms: "",
                is_send: false,  // 是否在60s内发送了短信
                sms_interval_tips: "获取验证码",
            }
        },
        created() {
            // 拦截已登录情况
            let token = this.$cookies.get('token');
            if (token) {
                this.$message({
                    message: '无需重复登录',
                    duration: 1000,
                    onClose: () => {
                        this.$router.go(-1)
                    }
                })
            }
        },
        methods: {
            // 高亮选项卡
            changeLogin(i) {
                this.login_type = i;
                if (i) {
                    this.a0 = 0;
                    this.a1 = 1;
                } else {
                    this.a0 = 1;
                    this.a1 = 0;
                }
            },

            loginAction() {
                if (!this.username || !this.password) {
                    return
                }
                this.$axios({
                    url: this.$settings.base_url + '/user/login/',
                    method: 'post',
                    data: {
                        'username': this.username,
                        'password': this.password,
                        'is_remeber': this.remeber

                    }
                }).then((response) => {
                    if (response.data.status == 0) {

                        let token = response.data.results.token;
                        let username = response.data.results.username;
                        // 判断用户是否要记住密码
                        if (this.remember) {  // 记住密码
                            this.$cookies.set('token',token,-1);
                            this.$cookies.set('username',username,-1);
                        } else { /// 没记住密码
                            this.$cookies.set('token',token,"0");
                            this.$cookies.set('username',username,"0");
                        }
                        this.$alert("欢迎回来!", "登录成功!", {
                            confirmButtonText: '确定',
                            callback: () => {
                                // 登录成功去主页
                                this.$router.push("/");
                            }
                        })
                    } else {
                        this.username = '';
                        this.password = '';
                    }


                }).catch(() => {
                    this.$alert("检查账号密码!", "登录失败!", {
                        confirmButtonText: '确定',
                        callback: () => {
                            this.username = '';
                            this.password = '';
                        }
                    });

                })
            },

            send_sms() {
                // 发送短信
                if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
                    this.$message({
                        message: "对不起!手机号码格式有误!"
                    });
                    return false;
                }

                // 判断是否在60s内发送过短信
                if (this.is_send) {
                    this.$message({
                        message: "对不起,不能频繁发送短信验证!"
                    });
                    return false;
                }

                // 请求发送短信
                this.$axios({
                    url: this.$settings.base_url + '/user/sms/',
                    method: 'post',
                    data: {
                        mobile: this.mobile
                    }
                }).then(response => {
                    let msg = response.data.msg;
                    this.$message({
                        message: msg,
                    });
                    if (msg === '短信发送失败') return;

                    // 修改短信的发送状态
                    this.is_send = true;

                    // 设置间隔时间60s
                    let sms_interval_time = 60;
                    // 设置短信发送间隔倒计时,.60s后把is_send改成false
                    let timer = setInterval(() => {
                        if (sms_interval_time <= 1) {
                            clearInterval(timer);
                            this.sms_interval_tips = "获取验证码";
                            this.is_send = false; // 重新回复点击发送功能的条件
                        } else {
                            sms_interval_time -= 1;
                            this.sms_interval_tips = `${sms_interval_time}秒后再次获取`;
                        }
                    }, 1000);

                }).catch(error => {
                    this.$message({
                        message: error.response.data.result,
                    })
                });

            },

            loginMobile() {
                // 注册信息提交
                if (!/^1[3-9]\d{9}$/.test(this.mobile)) {
                    this.$message({
                        message: "对不起!手机号码格式有误!"
                    });
                    return false;
                }

                if (this.sms.length < 1) {
                    this.$message({
                        message: "短信验证码不能为空!"
                    });
                    return false;
                }

                this.$axios({
                    url: this.$settings.base_url + '/user/login/',
                    method: 'post',
                    data: {
                        username: this.mobile,
                        code: this.sms,
                        is_remeber: this.remember,
                    }
                }).then(response => {
                    let _this = this;
                    let status = response.data.status;
                    let msg = response.data.msg;
                    if (status == 0) {
                        // cookie存储token,保存登录状态
                        let token = response.data.results.token;
                        let username = response.data.results.username;
                        console.log(this.remember);
                       if (this.remember) {  // 记住密码
                            this.$cookies.set('token',token,-1);
                            this.$cookies.set('username',username,-1);
                        } else { /// 没记住密码
                            this.$cookies.set('token',token,"0");
                            this.$cookies.set('username',username,"0");
                        }

                        _this.$message({
                            message: '登录成功',
                            duration: 1000,
                            onClose() {
                                // // 保存登录状态
                                // sessionStorage.token = token;
                                // sessionStorage.username = response.data.results.username;
                                // sessionStorage.mobile = response.data.results.mobile;
                                // 跳转到主页
                                _this.$router.push('/');
                            }
                        });
                    }
                    else {
                        _this.mobile = '';
                        _this.sms = '';
                        _this.$message({
                            message: msg,
                        });
                    }

                }).catch(error => {
                    this.mobile = '';
                    this.sms = '';
                    this.$message({
                        message: error.response.data.result
                    });
                })

            },
        },

    };
</script>

Header.Vue

<template>
    <div class="header-box">
        <div class="header">
            <div class="content">
<!--                图标-->
                <div class="logo full-left">
                    <router-link to="/"><img @click="jump('/')" src="@/assets/img/logo.svg" alt=""></router-link>
                </div>
<!--                课程序列-->
                <ul class="nav full-left">
                    <li><span @click="jump('/course')" :class="this_nav=='/course'?'this':''">免费课</span></li>
                    <li><span @click="jump('/light-course')" :class="this_nav=='/light-course'?'this':''">轻课</span></li>
                    <li><span>学位课</span></li>
                    <li><span>题库</span></li>
                    <li><span>老男孩教育</span></li>
                </ul>
<!--                购物车以及登录注册-->
                <div class="login-bar full-right">
    <!--                    购物车-->
                    <div class="shop-cart full-left">
                        <img src="@/assets/img/cart.svg" alt="">
                        <span><router-link to="/cart">购物车</router-link></span>
                    </div>
<!--                    登录注册-->
                    <div class="login-box full-left">
                        <div v-if="!is_login">
                            <router-link to="/login">登录</router-link>
                            &nbsp;|&nbsp;
                            <router-link to="/register">注册</router-link>
                        </div>
                        <div v-else>
                            <router-link to="/user">{{ username }}</router-link>
                            &nbsp;|&nbsp;
                            <span @click="logoutAction">注销</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Header",
        data() {
            return {
                this_nav: "",
                is_login:"",
                username:"",
            }
        },
        created() {
            this.this_nav = localStorage.this_nav;
            this.this_nav = localStorage.this_nav;
            this.is_login = this.$cookies.get('token');
            this.username = this.$cookies.get('username');
        },
        methods: {
            jump(location) {
                // 改变永久仓库的值
                localStorage.this_nav = location;
                // vue-router除了提供router-link标签跳转页面以外,还提供了 js跳转的方式
                this.$router.push(location);
            },
            logoutAction() {
                this.is_login = false;
                this.username = '';
                this.$cookies.remove('token');
                this.$cookies.remove('username');
            }
        }
    }
</script>
posted @ 2019-12-14 20:10  张明岩  阅读(476)  评论(0编辑  收藏  举报