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')
set_cookie不支持中文解决办法
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包含相对时间和绝对时间,上面介绍的两种相对应

更多可见:HTTP max-age与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,默认修改之后才保存(默认
View Code

 对于用户登录状态,不止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 %}
前端使用

 

posted @ 2018-03-28 14:49  山上有风景  阅读(993)  评论(0编辑  收藏  举报