zoukankan      html  css  js  c++  java
  • 用django框架开发一个B2C购物网站用户注册知识点总结2

    一:用户部分:

    用户注册:

    用户注册序列化器:

      1 import re
      2 
      3 from django_redis import get_redis_connection
      4 from rest_framework import serializers
      5 
      6 from users.models import User
      7 
      8 
      9 class CreateUserSerializer(serializers.ModelSerializer):
     10     """创建用户序列化器类"""
     11     password2 = serializers.CharField(label='重复密码', write_only=True)
     12     sms_code = serializers.CharField(label='短信验证码', write_only=True)
     13     allow = serializers.CharField(label='是否同意协议', write_only=True)
     14     token = serializers.CharField(label='JWT Token', read_only=True)
     15 
     16     class Meta:
     17         model = User
     18         fields = ('id', 'username', 'password', 'mobile', 'password2', 'sms_code', 'allow', 'token')
     19 
     20         extra_kwargs = {
     21             'username': {
     22                 'min_length': 5,
     23                 'max_length': 20,
     24                 'error_messages': {
     25                     'min_length': '仅允许5-20个字符的用户名',
     26                     'max_length': '仅允许5-20个字符的用户名',
     27                 }
     28             },
     29             'password': {
     30                 'write_only': True,
     31                 'min_length': 8,
     32                 'max_length': 20,
     33                 'error_messages': {
     34                     'min_length': '仅允许8-20个字符的密码',
     35                     'max_length': '仅允许8-20个字符的密码',
     36                 }
     37             }
     38         }
     39 
     40     # (参数完整性,手机号格式,手机号是否已注册,是否同意协议,两次密码是否一致,短信验证码是否正确)
     41     def validate_username(self, value):
     42         """用户名不能是纯数字"""
     43         if re.match(r'^d+$', value):
     44             raise serializers.ValidationError('用户名不能都是数字')
     45 
     46         return value
     47 
     48     def validate_mobile(self, value):
     49         """手机号格式,手机号是否已注册"""
     50         # 手机号格式
     51         if not re.match(r'^1[3-9]d{9}$', value):
     52             raise serializers.ValidationError('手机号格式不正确')
     53 
     54         # 手机号是否已注册
     55         count = User.objects.filter(mobile=value).count()
     56         if count > 0:
     57             raise serializers.ValidationError('手机号已存在')
     58 
     59         return value
     60 
     61     def validate_allow(self, value):
     62         """是否同意协议"""
     63         if value != 'true':
     64             raise serializers.ValidationError('请同意协议')
     65         return value
     66 
     67     def validate(self, attrs):
     68         """两次密码是否一致,短信验证码是否正确"""
     69         # 两次密码是否一致
     70         password = attrs['password']
     71         password2 = attrs['password2']
     72 
     73         if password != password2:
     74             raise serializers.ValidationError('两次密码不一致')
     75 
     76         # 短信验证码是否正确
     77         # 获取真实的短信验证码内容
     78         mobile = attrs['mobile']
     79         redis_conn = get_redis_connection('verify_codes')
     80         real_sms_code = redis_conn.get('sms_%s' % mobile) # bytes
     81 
     82         if not real_sms_code:
     83             raise serializers.ValidationError('短信验证码已过期')
     84 
     85         # 对比
     86         sms_code = attrs['sms_code'] # str
     87         real_sms_code = real_sms_code.decode() # str
     88         if sms_code != real_sms_code:
     89             raise serializers.ValidationError('短信验证码错误')
     90 
     91         return attrs
     92 
     93     def create(self, validated_data):
     94         """保存注册用户信息"""
     95         # 清除无用的数据
     96         del validated_data['password2']
     97         del validated_data['sms_code']
     98         del validated_data['allow']
     99 
    100         # # 调用父类create方法
    101         # user = super().create(validated_data)
    102         #
    103         # # 对密码进行加密
    104         # password = validated_data['password']
    105         # user.set_password(password)
    106         # user.save()
    107 
    108         # 调用create_user方法
    109         user = User.objects.create_user(**validated_data)
    110 
    111         # 注册成功就让用户处于登录状态
    112         # 由服务器签发一个jwt token,保存用户身份信息
    113         from rest_framework_jwt.settings import api_settings
    114 
    115         jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    116         jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    117 
    118         # 生成载荷信息(payload)
    119         payload = jwt_payload_handler(user)
    120         # 生成jwt token
    121         token = jwt_encode_handler(payload)
    122 
    123         # 给user对象增加一个属性token,保存jwt token信息
    124         user.token = token
    125 
    126         # 返回user
    127         return user
    对应视图函数:
     1 from django.shortcuts import render
     2 from rest_framework import status
     3 from rest_framework.response import Response
     4 from rest_framework.views import APIView
     5 from rest_framework.generics import GenericAPIView, CreateAPIView
     6 
     7 from users.models import User
     8 from users.serializers import CreateUserSerializer
     9 # Create your views here.
    10 
    11 
    12 # POST /users/
    13 # class UserView(GenericAPIView):
    14 class UserView(CreateAPIView):
    15     serializer_class = CreateUserSerializer
    16 
    17     # def post(self, request):
    18     #     """
    19     #     注册用户信息的保存:
    20     #     1. 获取参数并进行校验(参数完整性,两次密码是否一致,手机号格式,手机号是否已注册,短信验证码是否正确,是否同意协议)
    21     #     2. 保存注册用户信息
    22     #     3. 返回应答,注册成功
    23     #     """
    24     #     # 1. 获取参数并进行校验(参数完整性,两次密码是否一致,手机号格式,手机号是否已注册,短信验证码是否正确,是否同意协议)
    25     #     serializer = self.get_serializer(data=request.data)
    26     #     serializer.is_valid(raise_exception=True)
    27     #
    28     #     # 2. 保存注册用户信息(create)
    29     #     serializer.save()
    30     #
    31     #     # 3. 返回应答,注册成功
    32     #     return Response(serializer.data, status=status.HTTP_201_CREATED)
    33 
    34 
    35 # url(r'^usernames/(?P<username>w{5,20})/count/$', views.UsernameCountView.as_view()),
    36 class UsernameCountView(APIView):
    37     """
    38     用户名数量
    39     """
    40     def get(self, request, username):
    41         """
    42         获取指定用户名数量
    43         """
    44         count = User.objects.filter(username=username).count()
    45 
    46         data = {
    47             'username': username,
    48             'count': count
    49         }
    50 
    51         return Response(data)
    52 
    53 
    54 # url(r'^mobiles/(?P<mobile>1[3-9]d{9})/count/$', views.MobileCountView.as_view()),
    55 class MobileCountView(APIView):
    56     """
    57     手机号数量
    58     """
    59     def get(self, request, mobile):
    60         """
    61         获取指定手机号数量
    62         """
    63         count = User.objects.filter(mobile=mobile).count()
    64 
    65         data = {
    66             'mobile': mobile,
    67             'count': count
    68         }
    69 
    70         return Response(data)

    用到的知识点:

    ##### 2. JWT token
    
    1)session认证
    
    ```python
    1. 接收用户名和密码
    2. 判断用户名和密码是否正确
    3. 保存用户的登录状态(session)
        session['user_id'] = 1
        session['username'] = 'smart'
        session['mobile'] = '13155667788'
    4. 返回应答,登录成功
    ```
    
    session认证的一些问题:
    
    > 1. session存储在服务器端,如果登录的用户过多,服务器开销比较大。
    > 2. session依赖于cookie,session的标识存在cookie中,可能会有CSRF(跨站请求伪造)。                      
    
    2)jwt 认证机制(替代session认证)
    
    ```
    1. 接收用户名和密码
    2. 判断用户名和密码是否正确
    3. 生成(签发)一个jwt token(token中保存用户的身份信息) 公安局(服务器)=>签发身份证(jwt token)
    4. 返回应答,将jwt token信息返回给客户端。
    ```
    
    如果之后需要进行身份认证,客户端需要将jwt token发送给服务器,由服务器验证jwt token的有效性。
    
    3)jwt 的数据格式
    
    ```
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik
    pvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFO
    ```
    
    a)headers头部
    
    ```
    {
        "token类型声明",
        "加密算法"
    }
    ```
    
    base64加密(很容易被解密)
    
    b)payload(载荷):用来保存有效信息
    
    ```
    {
        "user_id": 1,
        "username": "smart",
        "mobile": "13155667788",
        "exp": "有效时间"
    }
    ```
    
    base64加密
    
    c)signature(签名):防止jwt token被伪造
    
    将headers和payload进行拼接,用.隔开,使用一个密钥(secret key)进行加密,加密之后的内容就是签名。
    
    jwt token是由服务器生成,密钥保存在服务器端。
    
    ##### 3. jwt 扩展签发jwt token
    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)

     

  • 相关阅读:
    MYSQL定时任务 触发器
    mybatis 学习
    SSM 记录
    环境变量配置
    servlet 拦截器 (filter)
    验证码
    jquery $.ajax({});参数详解
    maven打包忽略静态资源解决办法,dispatchServlet拦截静态资源请求的解决办法
    switch..case..
    HDU 1005 题解
  • 原文地址:https://www.cnblogs.com/168vincent/p/9606330.html
Copyright © 2011-2022 走看看