cookie与session

cookie 与 session:

cookie 与 session 原理:

​	1.保存客户端的用户状态

​	2.产生原因 : HTTP协议是无状态的(不会保存用户的状态)
cookie介绍 ;
	指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息

cookie查看 : 在浏览器上开发者模式,Network--->all---> Cookie

优点 :  服务端不用存储用户数据,减轻了服务器的压力

缺点 :  信息保存在客户端,信息不安全性增加(web领域内没有一定的安全)

django内操作Cookie

django内操作Cookie:
    #获取cookie : 
    request.COOKIES['key']    获取普通版cookie
    
	加盐版cookie (加密)
	request.get_signed_cookie(key,default=RAISE_ERROR,salt='',max_age=None)
    
    参数 : default :默认值  salt: 加密盐('')  max_age : 后台控制过期时间(单位:秒)

	#设置Cookie :
    1.方式一 : 在view.py中给返回给客户端的响应数据中设置Cookie
    rep = HttpResponse(...)  #获取 HttpResponse对象
	rep = render(request,...)   
	rep.set_cookie(key,value....)   #键值对形式

	2.方式二 :在view.py中给返回给客户端的响应数据中设置Cookie
    rep = HttpResponse(....)
	rep = render(request,...)
	rep.set_signed_cookie(key,value,salt='添加加密盐',....) 

	#删除cookie :
    def logout(request):
        rep = redirect('/login/')
        rep.delete_cookie('user')   # 清除客户端的cookie数据
        return rep

参数:
	key : 键   value : 值   
	path = '/': Cookie生效的路径,/ 表示根路径,根路径的cookie可以被任何url的页面访问
	demain = None , Cookie生效的域名
    secure = False, http传输
    httponly = False 只能http协议传输,无法被JavaScript获取

设置超时时间:

#设置超时时间:
  max_age 与 expires的区别:
	max_age = 秒    (不支持IE 浏览器)
    expires = 秒    (支持IE   浏览器)
    
    
    max_age : 超时时间 
    request.session.set_expiry(value)
    value : 整数 , datetime , none (django内的时间为准), 0 (关闭页面消失)
	request.session.set_expiry(value)
				* 如果value是个整数,session会在些秒数后失效。
				* 如果value是个datatime或timedelta,session就会在这个时间后失效。
				* 如果value是0,用户关闭浏览器session就会失效。
				* 如果value是None,session会依赖全局session失效策略。
注意:在django内默认的expire_data : 超时时间(2周)

cookie版登录:

from  functools import wraps
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')
        password = request.POST.get('password')
        if username == 'jason' and password == "123":
            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')

request.path_info   #只获取 url
request.get_full_path()  # 获取url + get 请求参数

session:

session介绍:

-cookie 的缺陷 : Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取

-session : 保存私密的信息以及超过4096字节的文本。保存在服务端
    	  --》工作机制需要依赖于cookie,在限定时间内 同一种上浏览器的session值相同,且在django内自动创建(django_session表 --需手动同步数据库),一种浏览器就对应一条数据

 创建session所发生的事件:
    1.djang内部自动帮你调用算法生成一个随机的字符串
    2.在django_session添加数据(数据也是加密处理)
    随机字符串         加密之后的数据           失效时间
    ashdjsad(key)         jsadsada(value)       set_expiry(value) 默认2周
    3.将产生的随机字符串返回给客户端浏览器 让浏览器保存
    sessionid:随机字符串

session相关方法:

#1. 获取 , 设置 , 删除 session内的数据
request.session['k1']= v1
.... 注意 : 先执行同步数据库命令生成django_session表;

request.session.get('k1')  

#删除: 
request.session.delete()    删除双方的所有session(只删除单个浏览器上的对应的数据) 
request.session.flush()    删除客服端 (推荐)

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

# 会话session的key
request.session.session_key

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

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

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

注意: django session 创建数据的时候,针对的是浏览器(创建数据的数据)
-->服务端数据只识别浏览器,不识别客服端的操作者!!!

django内session设置:

1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

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=随机字符串(默认)
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版登录验证:

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))

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

        if user == 'jason' and pwd == '123':

            request.session['user'] =  user
            next_url = request.GET.get('next')

            if next_url:
                return redirect(next_url)

            else:
                return redirect(request,'login/html')

@check_login
def logout(request):
    request.session.delete()

    return redirect('/login')
@check_login
def index(request):
    current_user = request.session.get('user',None)
    return render(request,'index.html',locals())

token

-能够作为数据库 : 
	1. 数据库软件 (关系型 , 非关系型)
    2. 文件 , 内存
    
    
 --》多用户下处理认证的最佳方式。

产生原因 :
    1.Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。

    2.可扩展性:在服务端的内存中使用Seesion存储登录信息,伴随而来的是可扩展性问题。

    3.CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。

    4.CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。
   
Token的优点 :
     1.无状态 ,可扩展 :客户端存储的Tokens是无状态的,并且能够被扩展

     2.安全性 :请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)

     3.可扩展性 :能够创建与其它程序共享权限的程序

     4.多平台跨域  :用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。

流程:
    1.用户登录校验,校验成功后就返回Token给客户端。

    2.客户端收到数据后保存在客户端

    3.客户端每次访问API是携带Token到服务器端。

    4.服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

原文地址:https://www.cnblogs.com/shaozheng/p/11985012.html