用户认证之cookie、session以及auth

一、cookie和session介绍

cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。

cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。


cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。


总结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。


二、cookie的简单使用

1、获取Cookie

request.COOKIES.get("islogin",None)  #如果有就获取,没有就默认为none

2、设置Cookie

  obj = redirect("/index/")

  obj.set_cookie("islogin",True)     #设置cookie值,注意这里的参数,一个是键,一个是值

  obj.set_cookie("haiyan","344",20)  #20代表过期时间

  obj.set_cookie("username", username)

3、删除Cookie

obj.delete_cookie("cookie_key",path="/",domain=name)     #path定义的是对那些路径生效,/表示对所有的url路径

4、cookie的优缺点

优点:数据存储在客户端。减轻服务端的压力,提高网站的性能

缺点:安全性不高,在客户端很容易被查看或破解用户会话信息


5、cookie登录示例

models.py文件内容:

class UserInfo(models.Model):
    username =models.CharField(max_length=32)
    password =models.CharField(max_length=32)


urls.py文件内容:

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^index/', views.index),
]


views.py文件内容:

from django.shortcuts import render,redirect,HttpResponse
from app01 import models

def login(request):
    if request.method=="POST":
        print("所有请求数据",request.POST)
        username = request.POST.get("username")
        password = request.POST.get("password")
        ret = models.UserInfo.objects.filter(username=username,password=password)   #判断用户输入的是否是数据库中的值
        if ret:                                    #如果用户名和密码都正确,则登录成功
            print(request.COOKIES)
            obj = redirect("/index/")
            obj.set_cookie("islogin",True)         #设置cookie值实现保持状态,注意这里的参数,一个是键,一个是值
            obj.set_cookie("haiyan","344",20)        #20代表过期时间
            obj.set_cookie("username", username)
            return obj
        else:
            return render(request,"login.html")
    else:
        return render(request,"login.html")
def index(request):
    is_login = request.COOKIES.get("islogin",None)        #得到cookie,有就得到,没有就得到none
    if is_login:
        username = request.COOKIES.get("username")
        return render(request,"index.html",{"username":username})
    else:
        return redirect("/login/")


login.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width">
    <title>用户登录</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <style>
        .c1{
            margin-top: 100px;
        }
        .btn{
            width: 130px;
        }
        .c2{
            margin-left: 40px;
        }
    </style>
</head>
<body>
<div>
    <div>
        <div class="c1 col-md-5 col-md-offset-3">
            <form action="/login/" method="post" novalidate>
                {% csrf_token %}
                <div>
                    <label for="username" class="col-sm-2 control-label">用户名</label>
                    <div>
                        <input type="email" id="username" placeholder="Email" name="username">
                    </div>
                </div>
                <div>
                    <label for="password" class="col-sm-2 control-label">密码</label>
                    <div>
                        <input type="password" name="password" id="password"
                               placeholder="Password">
                    </div>
                </div>
                <div>
                    <div class="col-sm-offset-2 col-sm-10">
                        <button type="submit" class="btn btn-primary">登录</button>
                        <button type="submit" class="btn btn-success c2">注册</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>


index.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width">
    <title>Title</title>
</head>
<body>
<h1>hello{{ username }}</h1>
</body>
</html>


三、session的简单使用

1、设置session值

    request.session["session_name"]="admin"

2、获取session值

    session_name = request.session("session_name")

3、删除session值

    del request.session["session_name"]  删除一组键值对

    request.session.flush()   删除一条记录

4、检测是否操作session值

    if "session_name"  is request.session:

5、用户session的随机字符串

        request.session.session_key


        # 将所有Session失效日期小于当前日期的数据删除

        request.session.clear_expired()

        # 检查 用户session的随机字符串 在数据库中是否

        request.session.exists("session_key")

        # 删除当前用户的所有Session数据

        request.session.delete("session_key")


        request.session.set_expiry(value)

            * 如果value是个整数,session会在些秒数后失效。

            * 如果value是个datatime或timedelta,session就会在这个时间后失效。

            * 如果value是0,用户关闭浏览器session就会失效。

            * 如果value是None,session会依赖全局session失效策略。


6、session流程分析

session会把信息保存在服务端,通常session和cookie配合使用。

(1)session设置

request.session["user_id"]=user.pk
request.session["username"]=user.user
内部实现机制如下:
'''
if request.COOKIE.get("sessionid"):      #浏览器能取到sessionid,对其进行更新操作
    更新sessionid的值
else:
    {"user_id": 1, "username": "wang"}
    第一步: 生成随机字符串: vwerascxh24asdasdasdsd
    第二步: 在django-sesion表生成一条记录:
    session - key             vwerascxh24asdasdasdsd
    session - data            {"user_id": 1, "username": "wang"}
    第三步:
    obj.set_cookie("sessionid", vwerascxh24asdasdasdsd)
'''


(2)session获取

request.session.get("user_id")
'''
第一步: request.COOKIE.get("sessionid"):vwerascxh24asdasdasdsd
第二步: 在django-sesion表查询一条记录:session-key=vwerascxh24asdasdasdsd
第三步: session-data({"user_id":1,"username":"alex"}).get("user_id")
'''


7、session登录示例

views.py文件内容:

def log_in(request):
    if request.method == "POST":
        username = request.POST['user']
        password = request.POST['pwd']
        user = UserInfo.objects.filter(username=username, password=password)
        if user:
            request.session['is_login'] = 'true'         #定义session信息
            request.session['username'] = username
            return redirect('/backend/')                 ## 登录成功就将url重定向到后台的url
    return render(request, 'login.html')
def backend(request):
    print(request.session, "------cookie")
    print(request.COOKIES, '-------session')
    """
    这里必须用读取字典的get()方法把is_login的value缺省设置为False,当用户访问backend这个url先尝试获取这个浏览器对应的session中的
    is_login的值。如果对方登录成功的话,在login里就已经把is_login的值修改为了True,反之这个值就是False的
    """
    is_login = request.session.get('is_login', False)
    if is_login:                            # 如果为真,就说明用户是正常登陆的
        cookie_content = request.COOKIES
        session_content = request.session
        username = request.session['username']
        return render(request, 'backend.html', locals())
    else:
        return redirect('/login/')
def log_out(request):
    """
    直接通过request.session['is_login']回去返回的时候,如果is_login对应的value值不存在会导致程序异常。所以需要做异常处理
    """
    try:
        del request.session['is_login']         # 删除is_login对应的value值
        #request.session.flush()                  # 删除django-session表中的对应一行记录
    except KeyError:
        pass
    return redirect('/login/')             #重定向回登录页面

login.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="post">
    <p>用户名: <input type="text" name="user"></p>
    <p>密码: <input type="password" name="pwd"></p>
    <p><input type="submit"></p>
</form>
</body>
</html>

backend.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>hello {{ username }}</h3>
<a href="/logout/">注销</a>
</body>
</html>

四、auth模块

auth_user                                    #保存了用户认证所需要的用户信息

python manage.py createsuperuser               #创建超级用户命令,然后根据提示输入相关信息,信息保存在auth_user中

from django.contrib import auth            #导入模块


1、authenticate()   :验证用户输入的用户名和密码是否相同

提供了用户认证,即验证用户名以及密码是否正确,一般需要username和password两个关键字参数

如果认证信息有效,会返回一个User对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。

2、login(HttpRequest, user):登录  

该函数接受一个HttpRequest对象,以及一个认证了的User对象

此函数使用django的session框架给某个已认证的用户附加上session id等信息。

3、logout(request)  注销用户 

该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

4、user对象的 is_authenticated()

要求:

(1)用户登录后才能访问某些页面

(2)如果用户没有登录就访问该页面的话直接跳转登录页面

(3)用户在跳转的登录界面中完成登录后,自动访问跳转到之前访问的地址

def my_view(request):

    if not request.user.is_authenticated():

        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))


五、User对象

User 对象属性:username, password(必填项)password用哈希算法保存到数据库

is_staff : 用户是否拥有网站的管理权限.

is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录


1、is_authenticated()

如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。

通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 这个方法可以 用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name


2、创建用户:create_user

from django.contrib.auth.models import User

user = User.objects.create_user(username='',password='',email='')

3、修改密码: set_password()

user = User.objects.get(username='')

user.set_password(password='')

user.save 


六、基于auth模块实现用户认证

urls.py文件内容:

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^index/', views.index),
    url(r'^logout/', views.logout),
    url(r'^reg/', views.reg),
]

views.py文件内容:

from django.shortcuts import render,redirect
from django.contrib import auth
from django.contrib.auth.models import User
def login(request):
    if request.method=="POST":
        user=request.POST.get("user")
        pwd=request.POST.get("pwd")
        print("before", request.user)
        user=auth.authenticate(username=user,password=pwd)
        if user:
            auth.login(request,user)                   # request.user:当前登录对象
            return redirect("/index/")
        else:
            s = "用户名和密码输入错误"
            return render(request, "login.html", {"s": s})
    return render(request,"login.html")
def index(request):
    if not request.user.username:
        return redirect("/login/")
    print(request.user)
    name=request.user.username
    return render(request,"index.html",{"name":name})
def logout(request):
    auth.logout(request)
    return redirect("/login/")
def reg(request):
    if request.method=="POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        User.objects.create_user(username=username,password=password)           #得到用户输入的用户名和密码创建一个新用户
        s = "恭喜你注册成功,现在可以登录了"
        return redirect("/login/")
    return render(request,"reg.html")


login.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    用户名 <input type="text" name="user">
    密码 <input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

index.html文件内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<h3>hi {{ name }}</h3>
<a href="/logout/">注销</a>
</body>
</html>





猜你喜欢

转载自blog.51cto.com/qidian510/2113253
今日推荐