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="data: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(){
}
}
});
django项目中账号注册登陆使用JWT的记录的更多相关文章
- 【技术博客】JWT的认证机制Django项目中应用
开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. JWT的认证机制Django项目中应用 这篇技术博客基于软 ...
- Django项目中添加富文本编辑器django-ckeditor
django-ckeditor库的使用步骤: 1.在命令行下安装django-ckeditor这个库: 命令:pip install django-ckeditor 2.安装成功后,配置Django项 ...
- [翻译]在Django项目中添加谷歌统计(Google Analytics)
原文:<Google Analytics tracking code into Django projects, the easy way> 对我来说,制作一个可扩展的Django应用随时 ...
- Django项目中使用Redis
Django项目中使用Redis DjangoRedis 1 redis Redis 是一个 key-value 存储系统,常用于缓存的存储.django-redis 基于 BSD 许可, 是一个使 ...
- 擦他丫的,今天在Django项目中引用静态文件jQuery.js 就是引入报错,终于找到原因了!
擦 ,今天在Django项目中引用静态文件jQuery.js 就是引入报错,终于找到原因了! 问题在于我使用的谷歌浏览器,默认使用了缓存,导致每次访问同一个url时,都返回的是缓存里面的东西.通过谷歌 ...
- django 项目中使用多数据库 multiple databases
假如在一个django项目中使用到了不只一个数据库, 其实这在大一点的工程中很常见,比如主从库 那么会涉及到如下一些东西 1, 定义 在settings中的DATABASE中定义会使用到的数据,比如除 ...
- django 项目中的 favicon.ico 处理
django 项目中的 favicon.ico 处理 (django == 2.0.6) 1. 引入模块: from django.views.generic.base import Redirec ...
- Django项目中模板标签及模板的继承与引用【网站中快速布置广告】
Django项目中模板标签及模板的继承与引用 常见模板标签 {% static %} {% for x in range(x) %}{% endfor %} 循环的序号{% forloop %} 循环 ...
- Django项目中"expected str, bytes or os.PathLike object, not list"错误解决:
对于这个错误,也在于自己对django基础的掌握不是很牢固,忽略了MEDIA_ROOT的类型是string,而不是list. 错误的写法: MEDIA_ROOT = [ os.path.join(BA ...
随机推荐
- 对https的研究
HTTPS简介 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP ...
- idhttp.get返回403错误解决办法
在GET之前,先指定UserAgent参数IdHTTP1.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; Ma ...
- VM虚拟机中MAC OS调整磁盘大小
1.打开终端,输入diskutil list: 2.从显示的列表中找到你需要扩展的分区(是分区不是磁盘,分区的ID一般为diskXsX): 3.然后输入 diskutil resizeVolume d ...
- POJ 2449 Remmarguts' Date ( 第 k 短路 && A*算法 )
题意 : 给出一个有向图.求起点 s 到终点 t 的第 k 短路.不存在则输出 -1 #include<stdio.h> #include<string.h> #include ...
- C++ 单链表模板类实现
单链表的C语言描述 基本运算的算法——置空表.求表的长度.取结点.定位运算.插入运算.删除运算.建立不带头结点的单链表(头插入法建表).建立带头结点的单链表(尾插入法建表),输出带头结点的单链表 #i ...
- Windows无法启动MapGIS DataStorage Service服务
但是启动又启动不了,查看属性 发现计算机服务器确实少了该文件目录.. 可能是不小心删除了? 之前确实有删过一些文件 下次直接把.net禁止就可以了,不用删除,不然不小心删除了其它服务.. 参考文献:h ...
- sql语句insert into where 错误解析
sql语句中,insert into 代表得是插入一条新得数据,全新得数据,所以你这样得写法是错误得,比如: "insert into klkl_Service_shop(name_real ...
- 表单修饰符 number、trim、lazy
number修饰符 <input type="number" v-model.number="age"> 结论:age 类型则为number,非字符 ...
- 123、TensorFlow的Job
# 如果你在分布式环境中部署TensorFlow # 你或许需要指定job name和task ID # 来将变量放置在参数服务器上 # 将操作放在worker job import tensorfl ...
- day17—Flex弹性布局详解(一)
转行学开发,代码100天——2018-04-02 今天看到一篇大神的文章,关于flex布局的详解,对flex用法介绍的相当详细,非常有助于我等初学者更深入了解这种布局方式. 文章链接 [基础知识]Fl ...