python-django of cookie and session

Cookie

The origin of Cookie

Http protocol is stateless

Stateless means are independent of each time there is a request, and the request of its implementation and the following results with the previous request are no direct relationship, it will not be directly affected by the response of the previous request, it does not directly affect the response of the latter request.

Word, the Bowl, on the server, every time the request is new

State data can be understood as a client and server created in a given session, and that no state to think that these data will not be saved. Data session is that we need to save, that 'save state'. Thus was born cookie

What is a cookie

cookie is a small piece of information refers specifically, it is sent to the server are stored in a set of keys to the browser, the next time you access the server browser will automatically carry these key-value pairs, in order to extract useful information server

A bundle of keys stored on the local browser

The principle cookie

Works cookie: generated by the server, the browser saved to a local receipt of the request; when the browser visits, the browser will automatically carry on a cookie, so the server can be judged by the content of this cookie who is a

View cookie

Chrome browser, open the developer tools.

cookie characteristics

  1. Let the server browser settings
  2. Visit the site carrying the corresponding cookie

Django operation cookie

1. Set the cookie

# 响应对象设置set_cookie
response.set_cookie('is_login','1')
response.set_cookie(key, value, max_age=5, path='/')
response.set_signed_cookie(key,value,salt='加密盐',...)

parameter:

  • key, key
  • value=''The value
  • max_age=None, overtime time
  • expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
  • path='/', Which entered into force Cookie path, / represents the root path, special: cookie root path can be accessed any url of the page
  • domain=None, Cookie domain name to take effect
  • secure=False, Https transmission
  • httponly=False Only http transmission protocol, JavaScript can not be acquired (not absolute, can get to the bottom of capture may be covered)

2. Get cookie

request.COOKIES  {}   value是字符串 
request.COOKIES.get('is_login')
request.get_signed_cookie('is_login',salt='xxxx',default='')

get_signed_cookieMethods of parameters:

  • default: Defaults
  • salt: Encryption Salt
  • max_age: Background control expiration
  • default=RAISE_ERROR: If there is no default cookie will error, so the custom settings to look better

3. Remove the cookie

def logout(request):
    rep = redirect(reverse('login'))
    rep.delete_cookie("user")  # 删除用户浏览器上之前设置的user的cookie值
    return rep

Login Cookie check

def login_required(func):
    @wraps(func)
    def inner(request,*args,**kwargs):
        is_login = request.COOKIES.get('is_login')
        if is_login != '1':
            url = request.path_info
            return redirect("{}?returnurl={}".format(reverse('login'),url))
        ret = func(request, *args, **kwargs)
        return ret
    return inner


class Login(View):
    http_method_names = ['get', 'post']

    def get(self, request, *args, **kwargs):
        return render(request, 'login.html')

    def post(self, request, *args, **kwargs):
        user_msg = request.POST.get('username')
        pass_msg = request.POST.get('password')
        user_obj = models.User.objects.filter(username=user_msg, password=pass_msg)
        if user_obj:
            ret_url = request.GET.get('returnurl')
            if ret_url is None:
                response = redirect(reverse('publisher'))
            else:
                response = redirect(ret_url)
            response.set_cookie('is_login','1')
            return response
        return render(request, 'login.html', {'login_error': '用户名或密码错误'})
    
    
## 第二版
def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.get_signed_cookie("login", salt="SSS", default=None) == "yes":
            # 已经登录的用户...
            return func(request, *args, **kwargs)
        else:
            # 没有登录的用户,跳转刚到登录页面
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        passwd = request.POST.get("password")
        if username == "xxx" and passwd == "dashabi":
            next_url = request.GET.get("next")
            if next_url and next_url != "/logout/":
                response = redirect(next_url)
            else:
                response = redirect("/class_list/")
            response.set_signed_cookie("login", "yes", salt="SSS")
            return response
    return render(request, "login.html")

Session

Although Cookie solved to a certain extent, a "hold" requirements, but due to the 4096 byte maximum support itself Cookie, Cookie and stored in the client itself, may be intercepted or stolen, and therefore there is a need for something new, it support more bytes, and he saved on the server, there is high security. This is the Session.

The question is, based on the characteristics of the stateless HTTP protocol, the server does not know the visitor "who." Then the aforementioned Cookie will play the role of bridge.

We can give each client Cookie assigned a unique id, so that users access by Cookie, the server knows to the people "who." Then we id different based on Cookie's, private information stored on the server for some time, such as "account password" and so on.

In conclusion: Cookie up for the lack HTTP stateless, let the server know to the people "who"; however Cookie in the form of text stored locally, their security is poor; so we can identify the user through different Cookie, corresponding saving private information and text than 4096 bytes in the Session.

Further, the above-mentioned fact, Cookie and Session commonality things, not limited to the language and the frame.

A bundle of keys stored on the server, you must rely on cookie

Why should the session?

  1. local cookie in your browser, unsafe
  2. cookie size limit is received

The method of operation of the Session Django

CRUD (session version)

# 设置session
# 当作字典使用即可
request.session[key] =value # 设置session 只能存储可被json序列化的 无法存储对象
request.session.setdefault('k1',123) # 存在则不设置

# 获取session
request.session[key]
request.session.get(key)

# 删除
del request.session['k1']
request.session.pop('k1')

request.session.delete()  # 删除所有的session数据  不删除cookie 
request.session.flush()   # 删除所有的session数据  删除cookie 
# 这用于确保前面的会话数据不可以再次被用户的浏览器访问
# 例如,django.contrib.auth.logout() 函数中就会调用它。

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 会话session的key
request.session.session_key

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。

# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()

Session flow analysis

Session Configuration

from django.conf import global_settings
from django.contrib.sessions.backends import db

1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)# 存储的位置
# cache  cache_db db file singed_cookies
# 支持 数据库 文件  缓存 缓存+数据库(redis) 加密cookie

2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其他公用设置项:
SESSION_COOKIE_NAME = "sessionid"          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)cookie的名字
SESSION_COOKIE_PATH = "/"                  # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None                # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False               # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True              # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600                # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False     # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False          # 是否每次请求都保存Session,默认修改之后才保存(默认)每次请求都更新session数据

django use redis do session cache

URL:https://django-redis-chs.readthedocs.io/zh_CN/latest/

Session version login authentication

from django.shortcuts import render, redirect, reverse, HttpResponse
from app01 import models
from django.views import View
from django.utils.decorators import method_decorator
from functools import wraps

def login_required(func):
    @wraps(func)
    def inner(request,*args,**kwargs):
        is_login = request.session.get('is_login')
        print(is_login)
        if not is_login:
            url = request.path_info
            return redirect("{}?returnurl={}".format(reverse('login'),url))
        ret = func(request, *args, **kwargs)
        return ret
    return inner

class Login(View):
    http_method_names = ['get', 'post']

    def get(self, request, *args, **kwargs):
        request.session.clear_expired()
        return render(request, 'login.html')

    def post(self, request, *args, **kwargs):
        user_msg = request.POST.get('username')
        pass_msg = request.POST.get('password')
        user_obj = models.User.objects.filter(username=user_msg, password=pass_msg)
        if user_obj:
            ret_url = request.GET.get('returnurl')

            # 设置session 只能存储可被json序列化的 无法存储对象
            request.session['is_login'] = user_msg
            # 设置session过期时间
            request.session.set_expiry(100)

            if ret_url is None:
                response = redirect(reverse('publisher'))
            else:
                response = redirect(ret_url)
            return response

        return render(request, 'login.html', {'login_error': '用户名或密码错误'})

@login_required
def singout(request):
    rep = redirect(reverse('login'))
    request.session.flush()
    return rep

@method_decorator(login_required,name='dispatch')
class PublisherList(View):
    def get(self, request, *args, **kwargs):
        all_publishers = models.Publisher.objects.all()
        return render(request, 'publisher_list.html', {'all_publishers': all_publishers})

Guess you like

Origin www.cnblogs.com/Anesthesia-is/p/11977491.html