zoukankan      html  css  js  c++  java
  • django项目中账号注册登陆使用JWT的记录

    需求分析

    1.  注册用JWT做状态保持
        1.1 安装jwt
        pip install djangorestframework-jwt
        
        1.2 去settings里面配置jwt配置项
        
            REST_FRAMEWORK = {
            'DEFAULT_AUTHENTICATION_CLASSES': (
                    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',# JWT认证,在前面的认证方案优先
                    'rest_framework.authentication.SessionAuthentication',
                    'rest_framework.authentication.BasicAuthentication',
                ),
            }
            JWT_AUTH = {
                'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), #JWT_EXPIRATION_DELTA 指明token的有效期
            }
        
        1.3 # 在注册或者登录之后,响应注册或者登录结果之前,生成jwt_token
            也就是users/serializers.py里面的create方法中添加
            
            
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            # 生成载荷:包含了user_id,username,email
            payload = jwt_payload_handler(user)
            # jwt_token
            token = jwt_encode_handler(payload)

            # 将token添加到user : python是面向对象的高级动态编程语言
            user.token = token
            
        1.4 在前端js/register.js文件中增加保存token
            var vm = new Vue({
            ...
            methods: {
                ...
                on_submit: function(){
                    axios.post(...)
                        .then(response => {
                            // 记录用户的登录状态
                            sessionStorage.clear();
                            localStorage.clear();
                            localStorage.token = response.data.token;
                            localStorage.username = response.data.username;
                            localStorage.user_id = response.data.id;
                            location.href = '/index.html';
                        })
                        .catch(...)
                }
            }
        })
        
        
        
    登陆

        1. 后端实现
        
        在users/urls添加路由
        
        from rest_framework_jwt.views import obtain_jwt_token

        urlpatterns = [
            url(r'^authorizations/$', obtain_jwt_token),
        ]
        
        2.在users/utils.py中,创建
        
            def jwt_response_payload_handler(token, user=None, request=None):
            """
            自定义jwt认证成功返回数据
            """
            return {
                'token': token,
                'user_id': user.id,
                'username': user.username
            }
        3.修改配置文件
            # JWT
            JWT_AUTH = {
                'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
                'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',
            }
            
        4.在users/utils.py中写:
        
            def get_user_by_account(account):
            """
            根据帐号获取user对象
            :param account: 账号,可以是用户名,也可以是手机号
            :return: User对象 或者 None
            """
            try:
                if re.match('^1[3-9]d{9}$', account):
                    # 帐号为手机号
                    user = User.objects.get(mobile=account)
                else:
                    # 帐号为用户名
                    user = User.objects.get(username=account)
            except User.DoesNotExist:
                return None
            else:
                return user


            class UsernameMobileAuthBackend(ModelBackend):
                """
                自定义用户名或手机号认证
                """

                def authenticate(self, request, username=None, password=None, **kwargs):
                    user = get_user_by_account(username)
                    if user is not None and user.check_password(password):
                        return user
        
        
        5. 在配置文件中告知Django使用我们自定义的认证后端
            AUTHENTICATION_BACKENDS = [
            'users.utils.UsernameMobileAuthBackend',
        ]
            
        
        6.修改login.html
        
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
            <head>
                <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
                <title>登录</title>
                <link rel="stylesheet" type="text/css" href="css/reset.css">
                <link rel="stylesheet" type="text/css" href="css/main.css">
                <script type="text/javascript" src="js/host.js"></script>
                <script type="text/javascript" src="js/vue-2.5.16.js"></script>
                <script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
            </head>
            <body>
                <div class="login_top clearfix">
                    <a href="index.html" class="login_logo"><img src="images/logo02.png"></a>    
                </div>
                <div class="login_form_bg" id='app'>
                    <div class="login_form_wrap clearfix">
                        <div class="login_banner fl"></div>
                        <div class="slogan fl">商品美 · 种类多 · 欢迎光临</div>
                        <div class="login_form fr">
                            <div class="login_title clearfix">
                                <a href="javascript:;" class="cur">账户登录</a>
                            </div>
                            <div class="form_con">
                                <div class="form_input cur">
                                    <form id="login-form" @submit.prevent="on_submit">
                                        <input type="text" v-model="username" @blur="check_username" name="" class="name_input" placeholder="请输入用户名或手机号">
                                        <div v-show="error_username" class="user_error" v-cloak>请填写用户名或手机号</div>
                                        <input type="password" v-model="password" @blur="check_pwd" name="pwd" class="pass_input" placeholder="请输入密码">
                                        <div v-show="error_pwd" class="pwd_error" v-cloak>{{ error_pwd_message }}</div>
                                        <div class="more_input clearfix">
                                            <input type="checkbox" v-model="remember">
                                            <label>记住登录</label>
                                            <a href="/find_password.html">忘记密码</a>
                                        </div>
                                        <input type="submit" name="" value="登 录" class="input_submit">
                                    </form>
                                </div>
                            </div>
                            <div class="third_party">
                                <a @click="qq_login" class="qq_login">QQ</a>
                                <a href="#" class="weixin_login">微信</a>
                                <a href="/register.html" class="register_btn">立即注册</a>
                            </div>

                        </div>
                    </div>
                </div>

                <div class="footer no-mp">
                    <div class="foot_link">
                        <a href="#">关于我们</a>
                        <span>|</span>
                        <a href="#">联系我们</a>
                        <span>|</span>
                        <a href="#">招聘人才</a>
                        <span>|</span>
                        <a href="#">友情链接</a>        
                    </div>
                    <p>CopyRight © 2016 北京xx商业股份有限公司 All Rights Reserved</p>
                    <p>电话:010-****888    京ICP备*******8号</p>
                </div>
                <script type="text/javascript" src="js/login.js"></script>
            </body>
            </html>
            
        7.修改login.js
        
            var vm = new Vue({
        el: '#app',
        data: {
            host: host,
            error_username: false,
            error_pwd: false,
            error_pwd_message: '请填写密码',
            username: '',
            password: '',
            remember: false
        },
        methods: {
            // 获取url路径参数    
            get_query_string: function(name){
                var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
                var r = window.location.search.substr(1).match(reg);
                if (r != null) {
                    return decodeURI(r[2]);
                }
                return null;
            },
            // 检查数据
            check_username: function(){
                if (!this.username) {
                    this.error_username = true;
                } else {
                    this.error_username = false;
                }
            },
            check_pwd: function(){
                if (!this.password) {
                    this.error_pwd_message = '请填写密码';
                    this.error_pwd = true;
                } else {
                    this.error_pwd = false;
                }
            },
            // 表单提交
            on_submit: function(){
                this.check_username();
                this.check_pwd();

                if (this.error_username == false && this.error_pwd == false) {
                    axios.post(this.host+'/authorizations/', {
                            username: this.username,
                            password: this.password
                        }, {
                            responseType: 'json',
                            withCredentials: true
                        })
                        .then(response => {
                            // 使用浏览器本地存储保存token
                            if (this.remember) {
                                // 记住登录
                                sessionStorage.clear();
                                localStorage.token = response.data.token;
                                localStorage.user_id = response.data.user_id;
                                localStorage.username = response.data.username;
                            } else {
                                // 未记住登录
                                localStorage.clear();
                                sessionStorage.token = response.data.token;
                                sessionStorage.user_id = response.data.user_id;
                                sessionStorage.username = response.data.username;
                            }

                            // 跳转页面
                            var return_url = this.get_query_string('next');
                            if (!return_url) {
                                return_url = '/index.html';
                            }
                            location.href = return_url;
                        })
                        .catch(error => {
                            if (error.response.status == 400) {
                                this.error_pwd_message = '用户名或密码错误';
                            } else {
                                this.error_pwd_message = '服务器错误';
                            }
                            this.error_pwd = true;
                        })
                }
            },
            // qq登录
            qq_login: function(){

            }
        }
    });
        
        
        
        
        
        
        
        
        
        
        

  • 相关阅读:
    Linux中的DHCP服务
    写出发帖数最多的前几条记录
    nginx和php-fpm调用方式
    redi集群测试
    Redis 3.2.1集群搭建
    linux系统centOS7下搭建redis集群中ruby版本过低问题的解决方法
    nginx与php-fpm通信的两种方式
    Linux安装mongodb总结
    php高并发
    thinkphp5报错
  • 原文地址:https://www.cnblogs.com/wxiaoyu/p/9588357.html
Copyright © 2011-2022 走看看