用户状态保持中间件源码分析

416 阅读2分钟

使用中间件签发token

'django.middleware.csrf.CsrfViewMiddleware',

session存储用户信息,验证用户状态 数据结构

# 1登录0非登陆状态
csrf_token = {
                'token1':'1',
                'token2':'0',
            }

创建使用用户中间件 user_middleware.py

'account.middleware.account_middleware'

伪代码

def account_middleware(get_response):
    print('init 被调用')

    def middleware(request):
        print('before request 被调用') # 访问接口
        # 获取csrftoken
        # csrftoken = None  pass
        # csrdtoken !=None 验证是否在cache中
        # if not in cache, set csrftoken
        # if in 返回 data
        csrftoken = request.COOKIES.get('csrftoken')
        if csrftoken == None:
            """
            首次登陆浏览器
            """
            pass
        else:
            """
            cache token
            """
            # 模拟缓存 1登录,0未登录
            csrf_token = {
                'token1':'1',
                'token2':'0',
            }
            if csrftoken not in csrf_token.keys:
                """
                token过期
                """
                pass
            else:
                """
                token验证通过,返回数据
                """
                if csrf_token.get(csrftoken) == 1:
                    """
                    登录用户
                    """
                    pass
                else:
                    """
                    非登录用户
                    """
                    pass
        response = get_response(request) # 执行view
        print('after response 被调用') # 返回数据
        return response

    return middleware

login view处理

views.py

    
def login(request):
    ...
    csrftoken = request.COOKIES.get('csrftoken')
    a = set_cache(csrftoken) # 将登录用户的token设为1
    ...

def set_cache(cached):
    """登录token处理"""
    mc.set(cached, 1, time=60 * 60 * 24)  # 免密登录,一天内有效
    return True

def get_cache(cached):
    """获取登陆状态"""
    is_ok = mc.get(cached)
    if is_ok:
        return True
    else:
        return False

1.用户进入系统,js验证是否登录

  • 前端验证方法,已经不需要,改为后端验证
function getCookie(cname)
{
  var name = cname + "=";
  var ca = document.cookie.split(';');
  for(var i=0; i<ca.length; i++) 
  {
    var c = ca[i].trim();
    if (c.indexOf(name)==0) return c.substring(name.length,c.length);
  }
  return "";
}

var username=getCookie("username");
if (username!="")
{
    alert("Welcome again " + username);
}else
{
    alert("请登录!")
}

2.后端验证是否登录

  • 获取到cookie中根路径"/"有username字段,返回index
  • 获取不到,重定向到login
def index(request):
    username = request.COOKIES.get('username')
    if not username:
        # 未登陆情况下跳转登录页
        return render(request, 'login.html', context={"pages": "登录"})
    return render(request, 'index.html', context={"pages": "首页"})

3.form表单登录请求

    <form method="post" action="/login/">
        <p>
            <label for="name">姓名:</label>
            <input type="text" id="name" name="username"> 
        </p>
       
        <p>
            <label for="pswd">密码:</label>
            <input type="password" id="pswd" name="pwd">
        </p>
      
        <input type="submit">
    </form>

4.视图验证信息

url.py

urlpatterns +=  path('login/', view.login),

view.py

def login(request):
    """
    用户登录
    """
    if request.method == 'POST':
        name = request.POST.get('name')
        password = request.POST.get('pwd')
        qs = Account.objects.filter(name=name)
        if not qs:
            return HttpResponse('用户名错误,重新登陆', status=400)
        password = hashlib.md5(password.encode('utf-8')).hexdigest()
        if qs[0].password != password:
            return HttpResponse('密码错误,重新登陆', status=400)
        # 登陆成功,返回首页视图
        return render(request, '/index.html', context={"username": name})
    else:
        # get请求,获取登录页
        return render(request, '/login.html')

5.首次登录设置cookie(username=username, timeout = 24h)

    <script>
        function setCookie(cname,cvalue,exdays)
        {
          var d = new Date();
          d.setTime(d.getTime()+(exdays*24*60*60*1000));
          var expires = "expires="+d.toGMTString();
          document.cookie = cname + "=" + cvalue + "; " + expires + "; path=/";
        }
        function getCookie(cname)
        {
          var name = cname + "=";
          var ca = document.cookie.split(';');
          for(var i=0; i<ca.length; i++)
          {
            var c = ca[i].trim();
            if (c.indexOf(name)==0) return c.substring(name.length,c.length);
          }
          return "";
        }
        function checkCookie()
        {
          var username=getCookie("username");
          if (username!=""){}
          else
          {
              setCookie("username","{{username}}",1);//1天有效
          }
        }
        checkCookie()
    </script>

6.登出处理

function login_out() {
    setCookie("username","",0);//删除cookie,过期时间设置为0,就好了
}
<a href="/login/" id="login_out" onclick="login_out()">点击登出</a>