一、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>
原文地址:http://blog.51cto.com/qidian510/2113253