学习python-Day58


今日学习内容

cookie与session

HTTP协议四大特性

1.基于请求响应
2.基于TCP、IP作用于应用层之上协议
3.无状态
	服务端无法识别客户端的状态
	HTTP是一种不保存状态,即无状态(stateless)协议。
	HTTP协议 自身不对请求和响应之间的通信状态进行保存。
    互联网刚开始兴起的时候,所有人访问网址都是一样的数据,服务端无法识别客户端问题。
    互联网发展后出现淘宝、京东、阿里,服务端不得不想办法记住客户端的状态。
    cookie与session应运而生。
4.无连接
保存在客户端上跟用户信息(状态)相关的数据

Session

保存在服务端上跟用户信息(状态)相关是数据

就是浏览器朝服务端发送请求,服务端保存用户信息,并以session方式返回给客户端里面存储一串随机字符串(令牌),保存在客服端上面。

session的工作需要依赖于cookie,就算目前所有能够识别用户身份的网址也需要使用cookie(客户端浏览器也有权拒绝保存cookie)。

image

.

image

django操作cookie

如果想要然客户端浏览器保存cookie需要HttpResonse对象调用的方法。


	return HttpResponse()
	return render()
	return redirect()
	return JsonRespone()

设置cookie需要变形

obj = HttpResponse()
obj.操作cookie的方法
return obj

obj = render()
obj.操作cookie的方法
return obj

obj = redirect()
obj.操作cookie的方法
return obj

obj = JsonResponse()
obj.操作cookie的方法
return obj
  1. 登录设置cookie

    def set_cookie(request):
        obj = HttpResponse('中秋快乐')
        # 让浏览器保存cookie数据
        obj.set_cookie('name', 'xz')
        return obj
    
    #login视图
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'jason' and password == '123':
                 obj.set_cookie('name', 'xz', max_age=3)
                 return obj
        return  render(request, 'login.html')
    
    #home视图
    def home(request):
        if request.COOKIES.get('name'):
        return HttpResponse('home页面 只有登录的用户才可以查看')
        return redirect('/login/')
    
    #首页视图
    def index(request):
        if request.COOKIES.get('name'):
        return HttpResponse('index页面 只有登录的用户才可以查看')
        return redirect('/login/')            
    

    问题:上述不管是有没有登录都是可以访问各个视图。

  2. 多个视图函数都需要校验用户是否登录:装饰器

    print(request.path)   路由后缀
    print(request.path_info) 路由后缀
    print(request.get_full_path) 全路径
    

    .

    多个视图装上装饰器

    @login_auth
    def home(request):
        return HttpResponse('home页面 只有登录的用户才可以查看')
    
    @login_auth
    def index(request):
        return HttpResponse('index页面 只有登录的用户才可以查看')     
    

    Cookie版登录验证(完整代码)

    def set_cookie(request):
        obj = HttpResponse('中秋快乐')
        # 让浏览器保存cookie数据
        obj.set_cookie('name', 'xz')
        return obj
    
    
    def login_auth(func_name):
        def inner(request, *args, **kwargs):
            if request.COOKIES.get('name'):
                res = func_name(request, *args, **kwargs)
                return res
            else:
                target_path = request.path_info
                return redirect(f'/login/?next={target_path}')
    
        return inner
    
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'xz' and password == '123':
                target_path = request.GET.get('next')
                if target_path:
                    obj = redirect(target_path)  # 如果有值则跳转到指定页面
                else:
                    obj = redirect('/home/')  # 如果没有值则跳转到首页
                obj.set_cookie('name', 'xz', max_age=3)
                return obj
        return render(request, 'login.html')
    
    
    @login_auth
    def home(request):
        return HttpResponse('home页面 只有登录的用户才可以查看')
    
    
    @login_auth
    def index(request):
        return HttpResponse('index页面 只有登录的用户才可以查看')
    
  3. 如果记住用户登录之前想要访问的页面,用户登录成功之后自动跳转

    场景1:用户访问了其他需要登录才可以访问的页面>>>:跳转到想要访问的。

    场景2:用户直接访问的登录页面>>>:网址首页

    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'jason' and password == '123':
                target_path = request.GET.get('next')
                if target_path:
                    obj = redirect(target_path)  # 如果有值则跳转到指定页面
                else:
                    obj = redirect('/home/')  # 如果没有值则跳转到首页
                obj.set_cookie('name', 'xz', max_age=3)
                return obj
        return render(request, 'login.html')
    

    注意: 参数max_agecookie保存信息时间长短。以为单位。

    总结

    1.首先用户访问某页面前是需要登录的,使用每个视图函数必须加个装饰器。
    2.如果用户请求后cookie有该键值对对应的值,则执行该视图函数。
    3.如果没有,则需要获取路由后缀或者全路径,返回并跳转到登录页面。
    4.用户登录后,拿到next后面的路由后缀并跳转,没有则跳转到首页。
    5.然后用户信息保存到cookie中。
    

    补充知识:

    获取Cookie和设置Cookie

    获取Cookie:
    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    ---------------------------------------------------------------------------
    参数:
    default: 默认值
    salt: 加密盐
    max_age: 后台控制过期时间
    

    .

    设置Cookie:
    rep = HttpResponse(...)
    rep = render(request, ...)
    
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)  
    -----------------------------------------------------------------------------------
    
    参数:
    expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
    path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
    domain=None, Cookie生效的域名
    secure=False, https传输
    httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
    

    删除Cookie

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

django操作session

设置djanjo操作sessionsession保存用户信息需要一张表。django_session需要提前执行数据库迁移命令。不然找不到那张表数据没法保存。

  1. 请求来的时候服务端会产生随机字符串并发送给客户端
  2. 服务端存储随机字符串与用户信息的对应关系
  3. 客户端携带随机字符串
  4. 服务端自动校验这些随机字符串
注意:django默认的session失效时间是14天
客户端会接收到的键值对,键默认是sessionid值是加密的随机字符串(令牌)

image

.

image

设置Session和获取Session的值

def set_session(request):
    request.session['name'] = 'xz'
    return HttpResponse('设置session')

def get_session(request):
    print(request.session.get('name'))
    return HttpResponse('获取session')

.

request.session['name'] = 'jason'
	1.django自动产生一个随机字符串返回给客户端(对name加密)
    2.往django_session创建数据(对xz加密)
request.session.get('name')
	1.自动重启请求中回去sessionid对应的随机字符串
    2.拿着随机字符串去django_session中匹配数据
    3.如果匹配上还会自动解密数据并展示

.

Session的存储位置有五种模式

  1. 数据库
  2. 缓存数据库
  3. 文件
  4. 缓存+数据库
  5. 加密

Session其他操作

# 删除当前会话的所有Session数据
    request.session.delete()
# 删除当前的会话数据并删除会话的Cookie。
    request.session.flush() 
request.session.set_expiry(value)
	*如果value是个整数,session会在些秒数后失效
    *如果value是个datatime或timedelta,session就会在这个时间失效
    *如果value是个0,用户关闭浏览器session就会失效
    *如果value是个None,session会依赖全局session失效策略
 

Session版登录验证(完整代码)

from functools import wraps
def check_login(func):
    @wraps(func)
    def inner(request, *args, **kwargs):
        next_url = request.get_full_path()
        if request.session.get("user"):
            return func(request, *args, **kwargs)
        else:
            return redirect("/login/?next={}".format(next_url))
    return inner


def login(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")

        if user == "xz" and pwd == 123:
            # 设置session
            request.session["user"] = user
            # 获取跳到登陆页面之前的URL
            next_url = request.GET.get("next")
            # 如果有,就跳转回登陆之前的URL
            if next_url:
                return redirect(next_url)
            # 否则默认跳转到index页面
            else:
                return redirect("/index/")
    return render(request, "login.html")


@check_login
def logout(request):
    # 删除所有当前请求相关的session
    request.session.delete()
    return redirect("/login/")


@check_login
def index(request):
    current_user = request.session.get("user", None)
    return render(request, "index.html", {"user": current_user})

django中间件简介

官方说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。

中间件帮助我们在视图函数中执行之后都可以做一些额外的操作。

  1. django中间件类似于django的门户,所有的请求很响应走都必须经过中间件。

  2. django默认自带七个中间件,每个中间件都有各自负责的功能

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
  3. 除了默认的之外还支持自定义中间件(无限加中间件)

  4. 中间件使用场景

    全局相关的功能:全局用户身份校验,全局用户黑名单校验,全局用户访问频率校验

  5. django自定义中间件中有五种方法

    process_request
    process_response
    process_view
    process_template_response
    process_exception
    
    方法 说明
    process_request 1.请求来的时候会按照配置文件中注册了中间件,
    从上往下依次执行每个中间件里面的process_request方法,
    如果没有则直接跳过。
    2.该方法如果返回了HttpResonse对象,那么请求不会再往后执行,原路返回
    process_response 1.响应走的时候会按照配置文件注册了的中间件,
    从下往上依次执行每个中间件里面process_response方法,
    如果没有则直接跳过。
    2.该方法有两个形参request和response,并且默认情况下返回response。
    3.该方法也可以自己返回HttpResponse对象,相当于狸猫换太子。
    process_view 当路由匹配成功之后,执行视图函数之前,自动触发。
    process_template_response(了解) 当视图函数返回的数据对象中含有render属性对应render函数才会触发。
    process_exception(了解) 当视图函数报错之后,自动触发。

    注意:如果请求的过程中process_request方法直接返回了HttpResponse对象那么会原地执行同级别process_response方法返回(flask则不同)。

    eg:创建一个文件夹utils里面是mymdd.py文件

    class MyMdd1(MiddlewareMixin):
        def process_request(self, request):
            print('MyMdd1 process_request')
            #如果请求有问题就可以直接返回HttpResponse的对象。退回去,就不会执行后面的内容了
            # return HttpResponse("我怀疑你有问题 你赶紧滚蛋!")
        def process_response(self, request, response):
            print('MyMdd1 process_response')
            return response
            # return HttpResponse('狸猫换太子')
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MyMdd1 process_view')
    
        def process_exception(self,request, exception):
            print(exception)
            print('MyMdd1 process_exception')
    
        def process_template_response(self, request, response):
            print('MyMdd1 process_template_response')
            return response
    
        
    class MyMdd2(MiddlewareMixin):
        def process_request(self, request):
            print('MyMdd2 process_request')
    
        def process_response(self, request, response):
            print('MyMdd2 process_response')
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print('MyMdd2 process_view')
    
    

    注意:

    1.对于process_response、process_template_response必须要返回一个形参response。
    不然返回的数据为空,没有返回的结果。
    2.针对视图函数有render方法,才能触发process_template_response中间件。
    
    
    def get_md(request):
        print('from get_md')
        def render():
            return HttpResponse("hahaha")
        obj = HttpResponse('嘿嘿嘿')
        obj.render = render
        return obj
    

    image

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/288672.html

(0)
上一篇 2022年9月10日
下一篇 2022年9月10日

相关推荐

发表回复

登录后才能评论