• Django--4、认证系统


    • cookie与session

      概念

      因http协议无法保存状态,但是又需要保存状态,所以有了cookie。它不属于http协议范畴

      工作原理:相当于一段标识数据。在访问服务器产生标识内容(cookie),加入到响应里返回,浏览器再次访问时会自动带上cookie。服务器就能识别出身份了。 数据缓存在浏览器中。减轻服务器端的压力。但安全性不高。

      cookie随可实现保持状态,但其最大支持4096字节,且保存在客户端不安全,于是产生了支持更多字节,保存在服务端的机制--session。

      session的机制:给客户端cookie加入不同的ID,访问时提供cookie,服务端根据ID拿出私密的数据,就可以识别出身份了。

      但是cookie中内容被盗依然危险,所以有了失效时间。

      总结:cookie与session要配合使用。cookie弥补了http无状态的不足,但存在客户端且安全性差。所以仅用cookie存标识号(sessionID),它对应服务端存的数据。

      是开发界共通的概念

      django实现cookie

      • 获取cookie
      request.COOKIES['key']
      request.get_signed_cookie(key,default=RAISE_ERROR,salt='',max_age=None)
          default:默认值
          salt:加密盐
          max_age:过期时间
      
      • 设置cookie
      res = 任何一种响应方式实例对象。
      res.set_cookie(key,value,……)
      res.set_signed_cookie(key,value,salt='加密盐',……)
      
      def set_cookie(self, key,                         value='',                    max_age=None,        超长时间
              expires=None,        超长时间
              path='/',           Cookie生效的路径,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
                            / 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
                   
                      domain=None,         Cookie生效的域名
                          你可用这个参数来构造一个跨站cookie如, domain=".example.com"
                          所构造的cookie对下面这些站点都是可读的:
                            www2.example.com 
                  和an.other.sub.domain.example.com 如果该参数设置为 None ,cookie只能由设置它的站点读取。
      
              secure=False,        如果设置为 True ,浏览器将通过HTTPS来回传cookie        httponly=False       只能http协议传输,无法被JavaScript获取
                              (不是绝对,底层抓包可以获取到也可以被覆盖)
                ): pass
      

      由于cookie保存在客户端,所以,JavaScript和jquery也可以操作cookie。

      <script src='/static/js/jquery.cookie.js'>
       
      </script> $.cookie("key", value,{ path: '/' });
      
      • 删除cookie res.delete_cookie("cookie_key",path="/",domain=name)

      Django实现session

      设置session值
      request.session['sname']="root"
      
      获取session值
      sname = request.session['sname']
      
      删除session值
      del request.session['sname']
      
      检测是否操作sessionif "sname" is request.session
      
      .get
      .pop
      .keys
      .items
      .setdefault
      .flush  删数据和cookie
      .session_key
      .clear_expired
      .exists
      .delete  删数据
      
      .set_expiry(value)
                  * 如果value是个整数,session会在些秒数后失效。
                  * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                  * 如果value0,用户关闭浏览器session就会失效。
                  * 如果value是None,session会依赖全局session失效策略。
      

      流程解析图

      1. 登录后生产个字典,字典存入session库,key是随机标识。value是数据字典
      2. 在value中存信息。
      3. 把Key写入cookie中返回,request.session看到的是value。

      总结:Django中用session时,cookie由服务端生成,写到请求里返回给浏览器。浏览器会缓存。cookie是寻找用户信息的唯一标识。

      session函数示例

      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:
                  #设置session内部的字典内容
                  request.session['is_login']='true'
                  request.session['username']=username
      
                  #登录成功就将url重定向到后台的url
                  return redirect('/backend/')
      
          #登录不成功或第一访问就停留在登录页面
          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:
              """
              如果访问的时候没有携带正确的session就直接被重定向url回login页面
              """
              return redirect('/login/')
      
      
      
      def log_out(request):
          """
          直接通过request.session['is_login']回去返回的时候,
          如果is_login对应的value值不存在会导致程序异常。所以
          需要做异常处理
          """
          try:
              #删除is_login对应的valuedel request.session['is_login']
              
              # OR---->request.session.flush() # 删除django-session表中的对应一行记录
      
          except KeyError:
              pass
          #点击注销之后,直接重定向回登录页面
          return redirect('/login/')
      
      ===================================login.html==================
      <!DOCTYPE html>
      <html lang="en">
      <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 lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      
      <h3>hello {{ username }}</h3>
      <a href="/logout/">注销</a>
      
      </body>
      </html>
      

      session存储的相关配置

      • 数据库配置(默认)
      Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
        
      a. 配置 settings.py
        
          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,默认修改之后才保存(默认)
      
      • 缓存配置
      a. 配置 settings.py
        
          SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
          SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
        
        
          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,默认修改之后才保存
      
      • 文件配置(了解)
      a. 配置 settings.py
        
          SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
          SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()        
          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,默认修改之后才保存
      

      用户认证

      auth模块

      导入

      from django.contrib import auth
      

      authenticate

      用户认证,需要user和password关键字参数,认证有效会返回user对象,该对象会在后续的登录过程中使用。

      login

      认证成功后登录并返回页面 接收一个HttpRequest对象,以及认证后生成的user对象。
      会给已认证的用户附加上sessionID等信息。

      logout

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

      login认证后user对象的is_authenticated

      判断认证是否通过。 不验证权限和激活状态。

      实现未登录跳到登录,登录后再跳回来。

      使用auth模块的 decorators的login_required方法。
      若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (在settings文件中通过LOGIN_URL进行修改)。并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

      auth.models的user对象

      is_staff 是否有管理权限
      is_active  是否允许登录
      

      创建用户create_user

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

      密码验证check_password

      接收密码字符串。
      用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True

      修改密码set_password

      user = User.objects.get(username='')
      user.set_password(password='')
      user.save 
      

      示例

      注册

      def sign_up(request):
       
          state = None
          if request.method == 'POST':
       
              password = request.POST.get('password', '')
              repeat_password = request.POST.get('repeat_password', '')
              email=request.POST.get('email', '')
              username = request.POST.get('username', '')
              if User.objects.filter(username=username):
                      state = 'user_exist'
              else:
                      new_user = User.objects.create_user(username=username, password=password,email=email)
                      new_user.save()
       
                      return redirect('/book/')
          content = {
              'state': state,
              'user': None,
          }
          return render(request, 'sign_up.html', content)  
      

      改密码

      @login_required
      def set_password(request):
          user = request.user
          state = None
          if request.method == 'POST':
              old_password = request.POST.get('old_password', '')
              new_password = request.POST.get('new_password', '')
              repeat_password = request.POST.get('repeat_password', '')
              if user.check_password(old_password):
                  if not new_password:
                      state = 'empty'
                  elif new_password != repeat_password:
                      state = 'repeat_error'
                  else:
                      user.set_password(new_password)
                      user.save()
                      return redirect("/log_in/")
              else:
                  state = 'password_error'
          content = {
              'user': user,
              'state': state,
          }
          return render(request, 'set_password.html', content)
  • 相关阅读:
    Containers vs Serverless:本质区别是什么?
    博云 x 某农商行 | 银行信息化运维系统升级的最佳实践
    兼容传统应用,蓄力边缘云——博云胖容器解决方案
    使用Bookinfo应用测试Kuma服务网格
    干货 | 博云基于OVS自研容器网络插件在金融企业的落地实践
    开源分布式事务中间件Seata使用指南
    调研 | 5种分布式事务解决方案优缺点对比
    Ambassador,云原生应用的“门神”
    容器网络插件那么多,博云为什么基于OVS深度自研?
    观察 | 边缘云计算的概念理解
  • 原文地址:https://www.cnblogs.com/jinyudong/p/8463115.html
Copyright © 2020-2023  润新知