<html lang="en" >
<body>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<h1 id="django-rest-framework-jwt">Django REST framework JWT</h1>
<p><strong>我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT。</strong></p>
<p><strong>关于签发和核验JWT,我们可以使用Django REST framework JWT扩展来完成。</strong></p>
<p><a href="http://getblimp.github.io/django-rest-framework-jwt/" target="_blank">文档网站http://getblimp.github.io/django-rest-framework-jwt/</a></p>
<h2 id="安装配置">安装配置</h2>
<p>安装</p>
<pre><code class="lang-shell">pip install djangorestframework-jwt
</code></pre>
<p>配置</p>
<pre><code class="lang-python">REST_FRAMEWORK = {
<span class="hljs-string">'DEFAULT_AUTHENTICATION_CLASSES'</span>: (
<span class="hljs-string">'rest_framework_jwt.authentication.JSONWebTokenAuthentication'</span>,
<span class="hljs-string">'rest_framework.authentication.SessionAuthentication'</span>,
<span class="hljs-string">'rest_framework.authentication.BasicAuthentication'</span>,
),
}
JWT_AUTH = {
<span class="hljs-string">'JWT_EXPIRATION_DELTA'</span>: datetime.timedelta(days=<span class="hljs-number">1</span>),
}
</code></pre>
<ul>
<li>JWT_EXPIRATION_DELTA 指明token的有效期</li>
</ul>
<h2 id="使用">使用</h2>
<p>Django REST framework JWT 扩展的说明文档中提供了手动签发JWT的方法</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> rest_framework_jwt.settings <span class="hljs-keyword">import</span> api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
</code></pre>
<p>在注册成功后,连同返回token,需要在注册视图中创建token。</p>
<p>修改CreateUserSerializer序列化器,在create方法中增加手动创建token的方法</p>
<pre><code class="lang-python">from rest_framework_jwt.settings import api_settings
class CreateUserSerializer(serializers.ModelSerializer):
"""
创建用户序列化器
"""
...
token = serializers.CharField(label='登录状态token', read_only=True) # 增加token字段
class Meta:
...
fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow', 'token') # 增加token
...
def create(self, validated_data):
"""
创建用户
"""
# 移除数据库模型类中不存在的属性
del validated_data['password2']
del validated_data['sms_code']
del validated_data['allow']
user = super().create(validated_data)
# 调用django的认证系统加密密码
user.set_password(validated_data['password'])
user.save()
# 补充生成记录登录状态的token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user.token = token
return user
</code></pre>
<h4 id="前端保存token">前端保存token</h4>
<p>我们可以将JWT保存在cookie中,也可以保存在浏览器的本地存储里,我们保存在浏览器本地存储中</p>
<p>浏览器的本地存储提供了sessionStorage 和 localStorage 两种:</p>
<ul>
<li><strong>sessionStorage</strong> 浏览器关闭即失效</li>
<li><strong>localStorage</strong> 长期有效</li>
</ul>
<p>使用方法</p>
<pre><code class="lang-js">sessionStorage.变量名 = 变量值 <span class="hljs-comment">// 保存数据</span>
sessionStorage.变量名 <span class="hljs-comment">// 读取数据</span>
sessionStorage.clear() <span class="hljs-comment">// 清除所有sessionStorage保存的数据</span>
localStorage.变量名 = 变量值 <span class="hljs-comment">// 保存数据</span>
localStorage.变量名 <span class="hljs-comment">// 读取数据</span>
localStorage.clear() <span class="hljs-comment">// 清除所有localStorage保存的数据</span>
</code></pre>
<p>在前端js/register.js文件中增加保存token</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue({
...
methods: {
...
on_submit: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
axios.post(...)
.then(response => {
<span class="hljs-comment">// 记录用户的登录状态</span>
sessionStorage.clear();
localStorage.clear();
localStorage.token = response.data.token;
localStorage.username = response.data.username;
localStorage.user_id = response.data.id;
location.href = <span class="hljs-string">'/index.html'</span>;
})
.catch(...)
}
}
})
</code></pre>
</section>
</div>
</div>
</div>
<a href="../C02-Users/JWT.html" class="navigation navigation-prev " aria-label="Previous page: JWT"><i class="fa fa-angle-left"></i></a>
<a href="../C02-Users/Login.html" class="navigation navigation-next " aria-label="Next page: 登录"><i class="fa fa-angle-right"></i></a>
</div>
</div>
</body>
</html>