python---django使用cookie和session
在views中的调用:
def login(req): message='' if req.method == "POST": user = req.POST.get("username") pwd = req.POST.get("password") count = models.Administrator.objects.filter(username=user,password=pwd).count() if count: red = redirect("/index.html") timeout = datetime.datetime.now()+datetime.timedelta(seconds=3) red.set_cookie('username',user,expires=timeout)
rep.set_cookie("info",{"age":10,"name":'fa'})
return red
else:
message = "用户名或密码错误"
return render(req,"login.html",{'msg':message})
在视图中设置cookie是通过set_cookie方法完成的,而不是请求响应的,并且值是通过字符串返回给请求的。
补充:
设置cookie: newuser = username.encode('utf-8').decode('latin-1') response.set_cookie('uname',newuser) 获取cookie: if request.COOKIES.get('uname'): context['uname'] = request.COOKIES['uname'].encode('latin-1').decode('utf-8')
timeout = datetime.datetime.now()+datetime.timedelta(seconds=3)
datetime.timedelta主要用来对时间进行运算,如想要获取前一天的时间:
datetime.datetime.now()-datetime.timedelta(day=1)
....可以便捷获取时间值
获取cookie可以直接使用:
def index(req): # if req.COOKIES username = req.COOKIES.get('username',None) if username: return render(req,"index.html",locals()) else: return redirect("/login.html")
cookie设置参数了解:
expires过期时间设置:
timeout = datetime.datetime.now()+datetime.timedelta(seconds=3)
red.set_cookie('username',user,expires=timeout) #可以直接设置在哪个时间过期 #绝对时间
red.set_cookie('username',user,expires=10) #也可以直接设置过期时间:10秒以后 #相对时间
max_age设置过期时间:
def test(req): rep = HttpResponse("fa") if req.COOKIES.get('k1',None): print(req.COOKIES.get('k1',None)) else: rep.set_cookie('k1','v1',max_age=10) #默认是秒数 return rep
补充:set_cookie源码:
def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False): """ Sets a cookie. ``expires`` can be: - a string in the correct format, - a naive ``datetime.datetime`` object in UTC, - an aware ``datetime.datetime`` object in any time zone. If it is a ``datetime.datetime`` object then ``max_age`` will be calculated. """ value = force_str(value) self.cookies[key] = value if expires is not None: if isinstance(expires, datetime.datetime): if timezone.is_aware(expires): expires = timezone.make_naive(expires, timezone.utc) delta = expires - expires.utcnow() # Add one second so the date matches exactly (a fraction of # time gets lost between converting to a timedelta and # then the date string). delta = delta + datetime.timedelta(seconds=1) # Just set max_age - the max_age logic will set expires. expires = None max_age = max(0, delta.days * 86400 + delta.seconds) else: self.cookies[key]['expires'] = expires else: self.cookies[key]['expires'] = '' if max_age is not None: self.cookies[key]['max-age'] = max_age # IE requires expires, so set it if hasn't been already. if not expires: self.cookies[key]['expires'] = cookie_date(time.time() + max_age) if path is not None: self.cookies[key]['path'] = path if domain is not None: self.cookies[key]['domain'] = domain if secure: self.cookies[key]['secure'] = True if httponly: self.cookies[key]['httponly'] = True
其中max_age是相对时间,相对获取到cookie的当前时间多少秒后过期:
而expires包含相对时间和绝对时间,上面介绍的两种相对应
path设置cookie路径:
rep.set_cookie('k1','v1',max_age=10,path='/test.html') #只在该url中生效
只会在当前路径下/test.html中该cookie才会生效,其他视图下是看不到的
domain域名:
默认只在当前域名下存在,可以使用。测试域名可以修改本地hosts文件:
127.0.0.1 crm.xxx.com 127.0.0.1 brm.xxx.com
然后再修改settings文件,设置允许访问的域名:
ALLOWED_HOSTS = [ '172.17.164.5', 'crm.xxx.com', 'brm.xxx.com', 'www.py_test.com', #对于www开头的域名会无法访问(无效),所以最好使用其他域名
#Invalid HTTP_HOST header: 'www.py_test1.com:8000'. The domain name provided is not valid according to RFC 1034/1035.
'127.0.0.1', 'localhost' ]
def test(req): rep = HttpResponse("fa") if req.COOKIES.get('k1',None): print(req.COOKIES.get('k1',None)) else: rep.set_cookie('k1','v1',max_age=10,path='/test.html',domain="xxx.com") #只在该url中生效 return rep
设置为在xxx.com下的域名下都可以进行使用,分别用crm.xxx.com先访问,产生k1:v1键值对,发现在brm.xxx.com中可以正常打印出k1的值,所以域名设置成功
secure使用:访问时需要证书,对于https访问时,我们需要将secure设置为True才可以正常设置cookie
httponly安全设置:通过http可以获取cookie,但是使用js是无法获取该键值cookie,
只是在浏览器中进行了限制,数据包中还是可以获取到该cookie
签名cookie:
设置加密cookie(加密,设置签名,可以反解出来):
rep.set_sgined_cookie("username","dasf") #dasf:1f163c:rZVvDHeMayCj6kSy4A24UheKptE客户端获取的cookie就不会是明文消息
rep.set_signed_cookie("username","fawafa") #fawafa:1f162P:Hl-wrkRxjGeNidsyk0bOGTGqYIE;汉字会转码,也可以反解
获取加密cookie(解密):
req.get_signed_cookie("username")
索引把不敏感的信息放在客户端cookie中,重要的放在session中
session使用:
首先需要修改settings文件:
MIDDLEWARE = [ ...... ] 修改为: MIDDLEWARE_CLASSES = [ ...... ]
然后可以使用:
print("session:",req.session) #session对象 #req是请求体 获取数据方法: req.session[key] 设置方法: req.session[key]=val 删除方法: del req.session[key]
session也含有相关的参数(是函数):
class SessionBase(object): """ Base class for all Session classes. """ TEST_COOKIE_NAME = 'testcookie' TEST_COOKIE_VALUE = 'worked' __not_given = object() def __init__(self, session_key=None): self._session_key = session_key self.accessed = False self.modified = False self.serializer = import_string(settings.SESSION_SERIALIZER) def __contains__(self, key): return key in self._session def __getitem__(self, key): return self._session[key] def __setitem__(self, key, value): self._session[key] = value self.modified = True def __delitem__(self, key): del self._session[key] self.modified = True def get(self, key, default=None): return self._session.get(key, default) def pop(self, key, default=__not_given): self.modified = self.modified or key in self._session args = () if default is self.__not_given else (default,) return self._session.pop(key, *args) def setdefault(self, key, value): if key in self._session: return self._session[key] else: self.modified = True self._session[key] = value return value def set_test_cookie(self): self[self.TEST_COOKIE_NAME] = self.TEST_COOKIE_VALUE def test_cookie_worked(self): return self.get(self.TEST_COOKIE_NAME) == self.TEST_COOKIE_VALUE def delete_test_cookie(self): del self[self.TEST_COOKIE_NAME] def _hash(self, value): key_salt = "django.contrib.sessions" + self.__class__.__name__ return salted_hmac(key_salt, value).hexdigest() def encode(self, session_dict): "Returns the given session dictionary serialized and encoded as a string." serialized = self.serializer().dumps(session_dict) hash = self._hash(serialized) return base64.b64encode(hash.encode() + b":" + serialized).decode('ascii') def decode(self, session_data): encoded_data = base64.b64decode(force_bytes(session_data)) try: # could produce ValueError if there is no ':' hash, serialized = encoded_data.split(b':', 1) expected_hash = self._hash(serialized) if not constant_time_compare(hash.decode(), expected_hash): raise SuspiciousSession("Session data corrupted") else: return self.serializer().loads(serialized) except Exception as e: # ValueError, SuspiciousOperation, unpickling exceptions. If any of # these happen, just return an empty dictionary (an empty session). if isinstance(e, SuspiciousOperation): logger = logging.getLogger('django.security.%s' % e.__class__.__name__) logger.warning(force_text(e)) return {} def update(self, dict_): self._session.update(dict_) self.modified = True def has_key(self, key): return key in self._session def keys(self): return self._session.keys() def values(self): return self._session.values() def items(self): return self._session.items() def iterkeys(self): return self._session.iterkeys() def itervalues(self): return self._session.itervalues() def iteritems(self): return self._session.iteritems() def clear(self): # To avoid unnecessary persistent storage accesses, we set up the # internals directly (loading data wastes time, since we are going to # set it to an empty dict anyway). self._session_cache = {} self.accessed = True self.modified = True def is_empty(self): "Returns True when there is no session_key and the session is empty" try: return not bool(self._session_key) and not self._session_cache except AttributeError: return True def _get_new_session_key(self): "Returns session key that isn't being used." while True: session_key = get_random_string(32, VALID_KEY_CHARS) if not self.exists(session_key): break return session_key def _get_or_create_session_key(self): if self._session_key is None: self._session_key = self._get_new_session_key() return self._session_key def _validate_session_key(self, key): """ Key must be truthy and at least 8 characters long. 8 characters is an arbitrary lower bound for some minimal key security. """ return key and len(key) >= 8 def _get_session_key(self): return self.__session_key def _set_session_key(self, value): """ Validate session key on assignment. Invalid values will set to None. """ if self._validate_session_key(value): self.__session_key = value else: self.__session_key = None session_key = property(_get_session_key) _session_key = property(_get_session_key, _set_session_key) def _get_session(self, no_load=False): """ Lazily loads session from storage (unless "no_load" is True, when only an empty dict is stored) and stores it in the current instance. """ self.accessed = True try: return self._session_cache except AttributeError: if self.session_key is None or no_load: self._session_cache = {} else: self._session_cache = self.load() return self._session_cache _session = property(_get_session) def get_expiry_age(self, **kwargs): """Get the number of seconds until the session expires. Optionally, this function accepts `modification` and `expiry` keyword arguments specifying the modification and expiry of the session. """ try: modification = kwargs['modification'] except KeyError: modification = timezone.now() # Make the difference between "expiry=None passed in kwargs" and # "expiry not passed in kwargs", in order to guarantee not to trigger # self.load() when expiry is provided. try: expiry = kwargs['expiry'] except KeyError: expiry = self.get('_session_expiry') if not expiry: # Checks both None and 0 cases return settings.SESSION_COOKIE_AGE if not isinstance(expiry, datetime): return expiry delta = expiry - modification return delta.days * 86400 + delta.seconds def get_expiry_date(self, **kwargs): """Get session the expiry date (as a datetime object). Optionally, this function accepts `modification` and `expiry` keyword arguments specifying the modification and expiry of the session. """ try: modification = kwargs['modification'] except KeyError: modification = timezone.now() # Same comment as in get_expiry_age try: expiry = kwargs['expiry'] except KeyError: expiry = self.get('_session_expiry') if isinstance(expiry, datetime): return expiry if not expiry: # Checks both None and 0 cases expiry = settings.SESSION_COOKIE_AGE return modification + timedelta(seconds=expiry) def set_expiry(self, value): """ Sets a custom expiration for the session. ``value`` can be an integer, a Python ``datetime`` or ``timedelta`` object or ``None``. If ``value`` is an integer, the session will expire after that many seconds of inactivity. If set to ``0`` then the session will expire on browser close. If ``value`` is a ``datetime`` or ``timedelta`` object, the session will expire at that specific future time. If ``value`` is ``None``, the session uses the global session expiry policy. """ if value is None: # Remove any custom expiration for this session. try: del self['_session_expiry'] except KeyError: pass return if isinstance(value, timedelta): value = timezone.now() + value self['_session_expiry'] = value def get_expire_at_browser_close(self): """ Returns ``True`` if the session is set to expire when the browser closes, and ``False`` if there's an expiry date. Use ``get_expiry_date()`` or ``get_expiry_age()`` to find the actual expiry date/age, if there is one. """ if self.get('_session_expiry') is None: return settings.SESSION_EXPIRE_AT_BROWSER_CLOSE return self.get('_session_expiry') == 0 def flush(self): """ Removes the current session data from the database and regenerates the key. """ self.clear() self.delete() self._session_key = None def cycle_key(self): """ Creates a new session key, while retaining the current session data. """ data = self._session key = self.session_key self.create() self._session_cache = data if key: self.delete(key) # Methods that child classes must implement. def exists(self, session_key): """ Returns True if the given session_key already exists. """ raise NotImplementedError('subclasses of SessionBase must provide an exists() method') def create(self): """ Creates a new session instance. Guaranteed to create a new object with a unique key and will have saved the result once (with empty data) before the method returns. """ raise NotImplementedError('subclasses of SessionBase must provide a create() method') def save(self, must_create=False): """ Saves the session data. If 'must_create' is True, a new session object is created (otherwise a CreateError exception is raised). Otherwise, save() only updates an existing object and does not create one (an UpdateError is raised). """ raise NotImplementedError('subclasses of SessionBase must provide a save() method') def delete(self, session_key=None): """ Deletes the session data under this key. If the key is None, the current session key value is used. """ raise NotImplementedError('subclasses of SessionBase must provide a delete() method') def load(self): """ Loads the session data and returns a dictionary. """ raise NotImplementedError('subclasses of SessionBase must provide a load() method') @classmethod def clear_expired(cls): """ Remove expired sessions from the session store. If this operation isn't possible on a given backend, it should raise NotImplementedError. If it isn't necessary, because the backend has a built-in expiration mechanism, it should be a no-op. """ raise NotImplementedError('This backend does not support clear_expired().')
补充session全局配置:
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 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,默认修改之后才保存(默认
对于用户登录状态,不止cookie,session也可以来完成,设置session的过期时间为7天(或者更长),函数中修改配置
def login(req): .... req.session.set_expiry(60*60*24*7) //将用户信息保存 }
{% if req.session.user_info %} <a href="">{{ req.session.user_info.username }}</a>·<a href="">我的博客</a>·<a href="">管理</a>|<a href="/logout.html">退出</a> {% else %} <a href="/login.html">登录</a>|<a href="/register.html">注册</a> {% endif %}