파이썬 - 장고 인증 시스템 인증 모듈과 JWT

로그인 인증 백엔드 구현

장고의 기본 인증 시스템은 인증 모듈을 제공하고있다. 인증 시스템이 포함됩니다 :

  • 사용자 관리
  • 권한 [RBAC]
  • 사용자 그룹 [역할 그룹]
  • 암호 해시 시스템
  • 사용자 로그온 또는 양식 및보기의 내용을 표시
  • 플러그 가능 백엔드 시스템

장고의 기본 사용자 인증 메커니즘은 우리가 프로젝트에 JWT 인증 메커니즘을 소개 세션 메커니즘을 의존, 사용자 토큰 문자열에 저장된 자격 증명하고 달성하기 위해 우리를 도와, 장고의 인증 시스템을 도킹의 정체성 :

  • 사용자 데이터 모델
  • 사용자 암호의 암호화 및 인증
  • 사용자 권한 시스템

장고 사용자 모델 클래스

장고의 인증 시스템은 사용자의 데이터를 저장하기 위해 사용자 모델 클래스 사용자를 제공, 기본 사용자는 다음과 같은 일반적인 기본 필드를 포함 :

필드 이름 필드 설명
username 필요합니다. 150 자 이하. 사용자 이름은 포함 할 수 _영숫자, @,, + .-문자를.
first_name 옵션 blank=True(). 적은 30 자와 같은보다.
last_name 옵션 blank=True(). 적은 30 자와 같은보다.
email 옵션 blank=True(). 전자 메일 주소를 입력합니다.
password 필요합니다. 해시 된 암호 문자열. (장고는 원래 암호를 저장하지 않습니다). 원래 암호는 무한 길이의 제한이없고 모든 문자를 포함 할 수 있습니다.
groups 그리고 Group사이의 많은 관계.
user_permissions 그리고 Permission사이의 많은 관계.
is_staff 부울 값입니다. 사이트에 액세스 할 수 관리자 사용자를 설정합니다.
is_active 부울 값입니다. 사용자 계정이 활성화되어 있음을 나타냅니다. 사용자가 로그인 할 수 있는지 여부를 제어하는 ​​데 사용하지만, 계정의 상태의 사용에 대해 설명하지 않습니다.
is_superuser 여부는 슈퍼 사용자입니다. 슈퍼 사용자는 모든 권한을 갖습니다.
last_login 사용자가 로그인 한 마지막 시간입니다.
date_joined 시간이 만들어 계정. 계정이 생성되면, 기본 설정은 현재 날짜 / 시간입니다.
일반적인 방법 :
  • set_password( raw_password )

    주어진 원시 문자열로 사용자의 암호를 설정하고 암호를 담당합니다. 그것은 저장하지 않는 User개체를. None이다 raw_password, 암호는 사용할 수없는 암호로 설정됩니다.

  • check_password( raw_password )

    주어진 raw_password는 사용자의 실제 비밀번호의 경우 사용자 암호의 유효성을 검사 할 때, 그것은 True를 반환, 당신은 사용할 수 있습니다.

관리자 방법 :

입니다 Manager 메소드 User.objects.메소드 호출.

  • create_user( 이름 , 이메일 = 없음 , 암호 = 없음 , * * extra_fields )

    생성, 저장 및 반환 User개체를.

  • create_superuser( 이름 , 이메일 , 비밀번호 , * * extra_fields )

    create_user()동일하지만, 설정 is_staffis_superuserTrue.

하위 사용자 응용 프로그램 모듈을 만들기

cd luffyapi/apps/
python ../../manage.py startapp users

settings.py 파일에 등록 된 하위 응용 프로그램.

INSTALLED_APPS = [
		...
  	'users',
]

사용자 정의 모델 클래스 만들기

장고 모델 클래스 사용자 인증 시스템 및 방법이 매우 편리를 제공, 우리는이 모델 클래스를 사용할 수 있지만, 프로젝트 요구 사항은 사용자의 전화 번호를 저장하는 일부 필드는 프로젝트의 요구를 충족시킬 수 없다, 당신은 모델 클래스에 필드를 추가해야합니다.

장고가 제공하는 django.contrib.auth.models.AbstractUser확장 필드를 사용 장고 모델 클래스 사용자 인증 시스템, 추상 모델 클래스는 우리가 상속 할 수 있도록 사용자를.

우리는 애플 리케이션에서 장고 응용 프로그램 사용자, 구성 파일에 등록 된 사용자와 응용 프로그램을 만들 수 있습니다.

사용자는 models.py 좋은 응용 프로그램을 만들 사용자 모델 클래스를 정의합니다.

from django.db import models

# Create your models here.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
    mobile = models.CharField(max_length=15, unique=True, verbose_name="手机号码")
    avatar = models.ImageField(upload_to="avatar", null=True, blank=True, verbose_name="头像")
    
    class Meta:
        db_table = 'ly_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

사용자 모델은 우리의 사용자 정의 클래스를 직접 구성 파일에 우리의 사용자 정의 모델 클래스를 알리기 위해 장고의 필요성을 사용하여 인증 시스템을 장고 인증 시스템을 식별 할 수 없습니다.

구성 파일에 설정

AUTH_USER_MODEL = 'users.User'

AUTH_USER_MODEL매개 변수를 설정하는 点.표현 구분 应用名.模型类名.

참고 : 장고 첫 번째 데이터베이스 마이그레이션이 설정되기 전에 AUTH_USER_MODEL 매개 변수 여야을 위해 우리가 그렇지 않으면 알 수없는 오류가 이후의 사용을 발생할 수 있습니다 설정 제안했다.

데이터베이스 마이그레이션을 수행

python manage.py makemigrations
python manage.py migrate

실행 python manage.py migrate명령을 : 다음과 유사한 주어진 시스템 :

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration reversion.0001_squashed_0004_auto_20160611_1202 is applied before its dependency users.0001_initial on database 'default'.

이것은 원래 모델 사용되지 않는 사용자를 사용하여 하위 응용 프로그램의 복귀라는 사람이지만, 이제 데이터베이스는 기본 하위 애플리케이션으로 설정 한 users모델 등 충돌이 있었다. 이 충돌 그래서, 우리는 원본 파일 및 데이터베이스 마이그레이션이 해결 될 수있는 모든 정보를 삭제해야합니다.

백업 데이터베이스 정보

数据库备份   哪一张数据库那一张表(luffy)   库下的表直接点(luffy.)
mysqldump -uroot -p123456 luffy > luffy_2019_12_19.sql
解决步骤:
1. 备份数据库,删除关于用户原来的数据表信息和表结构[如果刚开始开发,则直接清除库中所有数据表即可。
2. 删除apps下面的所有子应用中migrations目录下除了__init__.py以外的所有迁移文件
3. 删除在django.contrib.admin和django.contrib.auth模块里面的migrations迁移文件,除了__init__.py
4. 删除在xadmin和reversion模块中的migrations的迁移文件,除了__init__.py。
5. 执行数据迁移,把备份数据,除了用户以外的全部恢复执行即可。
6. 使用manage.py createsuperuser创建管理员即可

장고 REST 프레임 워크 JWT

사용자 등록 또는 로그인 후, 우리는 사용자의 로그인 상태를 기록, 또는 사용자에 대한 인증 자격 증명을 만들려고합니다. 우리는 더 이상 JSON 웹 토큰 인증 메커니즘을 사용, 세션 인증 메커니즘을 사용하지 않습니다.

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT의 헌법

에 의해 문자열에 JWT정보의 세 가지정보 텍스트의 다음 세 가지로 구성되어 .링크는 JWT 문자열을 구성한다. 이 같이 :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

첫 번째 부분에서는 우리는 헤드 (헤더), 우리 (평면에 담지 항목 유사한 페이로드)의 부하를 호출 번째 부분을 호출하고, 셋째 부분은 비자 (서명)이다.

JWT의 머리는 두 가지 정보를 전달 :

  • 유형 선언, 여기 JWT입니다
  • 암호화 알고리즘의 주장은 일반적으로 HMAC SHA256 직접 사용

JSON이 같은 전체 머리 :

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

이어서 헤드 Base64로 암호화 (대칭을 해독 할 수있는 암호화 된), 상기 제 1 부분을 구성한다.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

유효 탑재량

로드 로컬 스토리지는 유효 정보이다. 이름은 항공기 수행 등의 제품에 특별히 의미, 이러한 효과적인 정보는 세 부분으로 구성

  • 선언
  • 공공 문
  • 개인 성명

표준 신고서 (권장하지만, 사용에 필수는 아닙니다) :

  • ISS : JWT 발행
  • 서브 : 사용자에 대한 JWT
  • AUD : 수신 측 JWT
  • 특급 : JWT 만료 시간을 만료 날짜는 시간의 문제보다 커야합니다
  • NBF : 시간이 JWT 전에 정의 무엇을 사용할 수 없습니다.
  • IAT : 시간의 문제 JWT
  • JTI : JWT 고유 ID는, 주로 재생 공격을 방지하기 위해, 한 번 토큰으로 사용됩니다.

공공 문 : 공공 선언 어떤 정보가 필요한 정보 또는 다른 비즈니스 요구 사항을 추가 할 수있는 사용자에 대한 일반 정보를 추가 할 수 있지만, 민감한 정보가 추가 할 클라이언트의 일부를 해독 할 수 있기 때문에 사용하지 않는 것이 좋습니다.

개인 성명 : 64 기수가 일부 정보는 일반 텍스트로 분류 될 수 있음을 의미 대칭 암호 해독되기 때문에 개인 문은 일반적인 정의로 성명 공급자와 소비자 인은 일반적으로 민감한 정보를 저장하지 않는 것이 좋습니다.

페이로드를 정의합니다 :

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "history": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
}

이어서 JWT의 제 2 부분을 제공하기 위해, 64 비트로 암호화.

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

서명

JWT는 비자 정보의 세 번째 부분은,이 비자 정보는 세 부분으로 구성되어 있습니다 :

  • 헤더 (64 기수 후)
  • 페이로드 (64 기수 후)
  • 비밀

헤더 부 요구 후베이스 64은베이스 64를 사용하여 암호화 된 페이로드를 암호화 후에 .염 암호화 헤더 다음 문자열 연결 조성물 및 선언 secret조합 암호화 및 제 3 부분은 JWT를 구성한다.

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

이러한 세 부분으로 .연결된 전체 문자열은 최종 JWT를 구성 :

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

참고 : 비밀은 서버의 개인 키 그래서 어떤 시나리오가 갈 공개되어서는 안에서 서버 측에서 또한 JWT 발생하는 문제는, 비밀, JWT의 발행 및 JWT를 인증하는 데 사용되는 서버 측에 저장됩니다. 클라이언트가 비밀을 알게되면, 클라이언트가 JWT 자기가 서명 될 수 있다는 것을 의미한다.

jwt的优点:
1. 可以很方便的完成分布式站点的单点登录
2. jwt主要保存在客户端,服务器只需要保存秘钥,所有降低服务器的存储眼里
3. jwt的载荷可以存储一些数据发送给客户端,客户端可以查看对应的载荷中的数据,所以可以用户进行双方数据传输

jwt的缺点:
1. jwt实现比传统的session要复杂
2. jwt的信息保存在客户端,所以一经发放,无法回收。在此过程中,不好控制。保存在客户端部的数据容易被用户操作。

발행 및 JWT의 검증을 위해, 우리는 전체에 장고 REST 프레임 워크 JWT 확장을 사용할 수 있습니다.

문서 웹 사이트

JWT 설치 구성

설치

pip install djangorestframework-jwt

구성

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
import datetime
JWT_AUTH = {
    # 设置客户端的jwt的exp的有效期为1天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
  • JWT_EXPIRATION_DELTA는 유효한 토큰 지정

JWT 생성

문서의 장고 REST 프레임 워크 JWT 확장은 JWT 발행 설명서의 방법을 제공

이 코드는 시간에 등록됩니다 있습니다, 우리는에 사용합니다.

from rest_framework_jwt.settings import 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)

사용자 등록 또는 로그인이 성공 후에는 미래가 될 수 토큰 수익률 시리얼 라이저에서 사용자 정보를 반환합니다.

인터페이스 로그인 인증 백엔드 구현

장고 REST 틀 JWT 직접 사용할 수 로그인 토큰을 획득하는 뷰를 제공

하위 응용 프로그램에서 urls.py에서 라우팅

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path(r'login/', obtain_jwt_token),
]

주요 노선에서, 현재의 하위 응용 프로그램 라우팅 파일의 도입

urlpatterns = [
		...
    path('users/', include("users.urls")),
    # include 的值必须是 模块名.urls 格式,字符串中间只能出现一个圆点
]

다음으로, 우리는 우편 배달부에 의해 다음과 같은 기능을 테스트 할 수 있습니다

2.3.7 프런트 엔드는 JWT 저장

우리는 또한 브라우저의 로컬 메모리에 저장할 수있는 쿠키에 저장 JWT 수 있습니다, 우리는 브라우저 로컬 스토리지에 저장

로컬 저장소 브라우저 sessionStorage와 localStorage를 두 가지 방법을 제공합니다 :

  • sessionStorage의 브라우저는 소멸된다 폐쇄
  • 로컬 스토리지는 장기 효과

용도

sessionStorage.变量名 = 变量值   // 保存数据
sessionStorage.setItem("变量名","变量值");  // 保存数据
sessionStorage.变量名  // 读取数据
sessionStorage.getItem("变量名")  // 读取数据
sessionStorage.removeItem("变量名") // 删除一个数据
sessionStorage.clear()  // 清除所有sessionStorage保存的数据

localStorage.变量名 = 变量值   // 保存数据
localStorage.setItem("变量名","变量值");  // 保存数据
localStorage.变量名  // 读取数据
localStorage.getItem("变量名")  // 读取数据
localStorage.removeItem("变量名") // 删除一个数据
localStorage.clear()  // 清除所有sessionStorage保存的数据

2.3.9 다중 조건 등록부

JWT는 사용자 이름과 암호를 수신 할 때, 로그인 뷰를 확장뿐만 아니라, 전화 **에서 제공하는 인증합니다 장고의 인증 시스템 () ** 사용자 이름과 암호가 올바른지 확인합니다.

우리는 사용자 이름이나 전화 번호 중 하나가 될 수있는 인증 백엔드 장고 인증 시스템 (주로 인증 할 방법)을 수정하여 로그인 계정을 지원할 수 있습니다.

수정 인증 백엔드 장고 인증 시스템 요구 django.contrib.auth.backends.ModelBackend을 상속하고,을 인증 메소드를 오버라이드 (override)합니다.

authenticate(self, request, username=None, password=None, **kwargs)매개 변수 설명 방법 :

  • 요청 인증 요청 개체
  • 사용자 이름 사용자가 제공이 인증 계정
  • 이 암호 인증 암호를 제공합니다

우리는 사용자 이름으로, 당신은 또한을 인증 방법에 대한 다음 전화 번호로 로그인 할 수있는 사용자 중 하나를 로그인하게하려면, 사용자 이름 매개 변수 즉, 사용자 이름 또는 전화 번호.

재 작성 아이디어를 인증 할 방법 :

  1. 사용자 사용자 개체 매개 변수의 이름을 찾습니다 따르면, 사용자 이름 매개 변수는 사용자 이름이 될 수 있습니다, 그것은 전화 번호 수 있습니다
  2. 는 사용자 개체를 찾을 수 있다면, 올바른 암호 사용자 개체 여부를 확인은 check_password 메소드를 호출

사용자 / utils.py에서의 쓰기 :

# jwt自定义返回函数
def jwt_response_payload_handler(token, user=None, request=None):
    """
    自定义jwt认证成功返回数据
    :parameter token 本次响应给客户端的jwt字符串
    :parameter user  本次查询出来的用户模型对象
    :parameter request  本次客户端的请求对象
    """
    return {
        'token': token,
        'id': user.id,
        'username': user.username
    }


"""自定义用户多条件认证"""
# pycharm自动导包 快捷键: 光标移动到对应的类名中,使用 Alt + Enter
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q


def get_account_by_user(username):
    """根据username获取用户信息"""
    from .models import User
    try:

        user = User.objects.get(Q(username=username) | Q(mobile=username))
    except User.DoesNotExist:
        user = None
    return user

class UsernameMobileAuthBackend(ModelBackend):
    """实现用户多条件登录"""
    def authenticate(self, request, username=None, password=None, **kwargs):
        user = get_account_by_user(username)
        if user is not None and user.check_password(password) and user.is_active:
            return user

장고 구성 파일 설정에 통보 / dev.py 사용 우리의 사용자 정의 인증 백엔드

AUTHENTICATION_BACKENDS = [
    'users.utils.UsernameMobileAuthBackend',
]

추천

출처www.cnblogs.com/zhaoganggang/p/12570819.html