zoukankan      html  css  js  c++  java
  • JWT认证原理及使用

    一、JWT原理:

      参考文章:https://www.jianshu.com/p/180a870a308a

      1、传统的登录方式:

        浏览器输入用户名密码,服务端校验通过,根据用户信息生成一个token,将token和user_id存到数据库或者session中,并将token返回给前端,存入cookie,后面浏览器每次请求都会带上cookie,服务端根据cookie查询用户,验证用户有效性。

        弊端:

          1)如果出现XSS(跨站脚本攻击)漏洞,由于cookie可以被js读取,XSS漏洞会导致用户token被泄露。

           解决方案:

            a)设置httpOnly,这样的话cookie将不会被js读取,浏览器会自动将它加到请求头信息中,但是带来了新的问题,很容易被XSRF(跨站请求伪造)攻击,因为只要当前浏览器开着,另一个界面可以很容易的跨站请求这个界面的内容,因为cookie会被默认发送出去。

            b)设置secure,这样cookie就只能通过https传输,可以过滤掉一些使用http协议请求的XSS注入。

          2)将验证信息存到数据库中,每次验证的时候,都需要去数据库中查询,增加了数据库的查询和存储开销。

          3)如果将token存到session中,也会增加服务器的存储压力。

      2、为什么使用 JWT

        1)可以通过URL POST参数或者http header中发送,数据量小,传输速度快。

        2)自包含:负载中包含了用户所需要的所有信息,避免多次查询数据库。

        3)JWT组成:

          header+payload+signature 三者通过点【.】连接起来就是JWT了。

          

          a)header头部:包含token类型和采用的加密算法

            {"alg":"HS256", "typ":"JWT"}

          b)payload负载:存放信息的地方,可以把用户ID等信息存放在payload中。

            常用的信息有:iss(签发者), exp(过期时间), sub(面向用户), aud(接收方), iat(签发时间)等。

          c)signature签名:使用编码后(base64编码)的header和payload再加上我们提供的一个公钥,然后使用header中指定的签名算法进行签名。作用是保证JWT没有被窜改过。

          JWT只适合向web端传递一些非敏感信息,因为base64编码是可逆的,很容易被破解。

          JWT通常用来设计用户认证和授权系统,还有我们通常说的单点登录等。

    二、JWT的使用过程

            

      1)前端通过表单将用户名和密码发送到后端接口。

      2)后端核对用户名和密码后,将用户的id及其他非敏感信息作为JWT Payload,将其与头部分别进行base64编码后签名,生成JWT

        具体源代码见rest_framework_jwt下面的serializer中,有兴趣研究的可以去跟踪看看

        

      3)后端将JWT字符串作为登录成功的结果返回给前端,前端可以将JWT存到localStorage或者sessionStorage中,退出登录时,前端删除保存的JWT信息即可。

      4)前端每次在请求时,将JWT放到header中的Authorization

      5)后端验证JWT的有效性

      6)验证通过后,进行其他逻辑操作。

    三、JWT使用方法:

      1、安装

        pip install djangorestframework-jwt

      2、将JSONWebTokenAuthentication加到settings.py中的DEFAULT_AUTHENTICATION_CLASSES中,它可以将用户post过来的数据进行验证,并将user取出来,它和MIDDLEWARE中的AuthenticationMiddleware的原理是一样的。

        

      3、配置JWT的认证接口的url

        from djangorestframework-jwt.views import obtain_jwt_token

        url(r"^login$", obtain_jwt_token)

      4、前端访问 login,传入用户名和密码,服务器会给浏览器返回一段token(jwt)

        {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MzEzNzU4NjEsImVtYWlsIjoiMzcwMTkzNTkzQHFxLmNvbSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.BIl1b68VV-LvZOu-wrUeMxUFI3IREapgqfbTtzB6Ftw"}

      5、在后面的请求中,将JWT token信息 加入到header中的authorization中。

      6、扩展:

        DRF默认是通过邮箱作为用户名来登录的,所以如果我们是通过手机或者其他方式登录的话,需要重写DRF的认证方式。

        from django.db.models import Q

        from django.contrib.auth.backends import ModelBackend

        from django.contrib.auth import get_user_model

        User = get_user_model()

        class CustomBackend(ModelBackend):

          def authenticate(self, request, username=None, password=None, **kwargs):

            try:

              user = User.objects.get(Q(username=username) | Q(mobil = username))

              if user.check_password(password):

                return user

              else:

                return None 

            except Exception as e:

              return None

       7、将重写的CustomBackend加入到settings中

        

      8、JWT的额外设置:

        

  • 相关阅读:
    SQL 脚本 重复执行 约束
    xiami 精选集
    PHP 5 环境配置
    Thread线程类
    创建线程
    C#中简单的正则表达式(也经常会用到的)
    线程的挂起与恢复
    C#操作INI文件
    多线程简介
    单线程简介
  • 原文地址:https://www.cnblogs.com/fiona-zhong/p/9951054.html
Copyright © 2011-2022 走看看