cookie实现记住密码和自动登录的功能

1.需求分析:

现在我们需要实现在原始页面中用户输入用户名和密码并点击记住密码按钮时,成功进入登录界面,然后点击退出登录后刷新原始页面,原始页面中自动保存着上一次的用户名和密码。
如果用户点击了自动登录,那么退出登录后刷新原始页面,原始页面会显示用户名和密码,并且在500ms后自动进入登录界面。
如果用户已经进入登录界面,再次刷新页面后,仍然在登录界面停留。
注意:这里的原始页面和登录页面是写在一个页面中的,我用透明度和层级来区分当前应该显示哪一个页面。

2.解决方案

  • 注:记住密码的cookie名为remMe,自动登录的cookie名为auto
    用户名的cookie名为username,密码的cookie名为password
  • 注:cookie名为name意为保存着登录状态,name值为true则始终会在登录界面,无这一cookie代表着退出了登录。这一cookie是在NodeJs中设置和删除的。
  • 补充知识:如何在前端js中得到相应的cookie呢?
//得到cookie名为name的value值
 function getCookie(name){
    
    
   var cookieArray=document.cookie.split(";");
   for(var i=0;i<cookieArray.length;++i){
    
    
    var cookies=cookieArray[i].split("=");
    if(cookies[0].trim()==name){
    
    
     return cookies[1];
    }
   }
   if(i==cookieArray.length){
    
    
    return "";
   }
  }
  //设置名为cname,值为cvalue,过期时间为exdays天的cookie
  //d.getTime()获得了1970年至此刻的时间毫秒差
  //d.toGMTString()是形如:Thu, 20 Feb 2020 07:54:01 GMT的时间
   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;
  }

1.只使用cookie,在前端js中设置cookie和删除cookie
分析:
(1)可以在前端js中监听点击确认登录的事件,一旦点击确定就可以判断记住密码和自动登录是否点击从而设置cookie,如果点击设置该cookie相应的值为true,如果未点击就设置该cookie相应的值为false。并且需要另外设置两个cookie来保存用户名和密码,只有选中记住密码或者自动登录时才会产生这两个cookie否则删除掉。
(2)在刷新页面时,前端js通过判断当前页面的remMe,auto这两个cookie的值为true或false而判断是否要将cookie名为username和password的值赋给原始页面的用户名和密码的input框以及通过cookie名为name的值判断登录界面是否显示。
部分代码如下:
注:这是以对象的方式来写的,这两个方法是写在一个对象里的。

//that.remember为记住密码的按钮,that.remember1为自动登录的按钮
//that.buttonTwo为确认登录的按钮
//可以实现(1)功能
rememberFunction: function(){
    
    
  var that=this;
  function addButtonTwo(){
    
    
	   if(that.remember.checked==true&&that.te2.value!="请输入用户名"&&that.pa2.value!="请输入密码"){
    
    
		    var name=that.te2.value;
		    var pass=that.pa2.value;
		    SetCookie("remMe","true",1);
		    SetCookie("username",name,1);
		    SetCookie("password",pass,1);    
	    }else{
    
    
	            SetCookie("remMe","false",1);
		    if(that.remember1.checked==false){
    
    
			     SetCookie("username","",-1);
			     SetCookie("password","",-1);
		    }
            }
	   if(that.remember1.checked==true&&that.te2.value!="请输入用户名"&&that.pa2.value!="请输入密码"){
    
    
		    var name=that.te2.value;
		    var pass=that.pa2.value;
		    SetCookie("auto","true",1);
		    SetCookie("username",name,1);
		    SetCookie("password",pass,1);
	    }else{
    
    
		    SetCookie("auto","false",1);
		    if(that.remember.checked==false){
    
    
		     SetCookie("username","",-1);
		     SetCookie("password","",-1);
		    }  
            }
     }
     that.buttonTwo.addEventListener('click',addButtonTwo);
 },
 //可以实现(2)功能
 //that.page2为登录界面, that.wrapper为原始界面, 
 //that.load代表原始页面中登录的输入信息框
 //that.te2代表输入用户名的input框,that.pa2代表输入密码的input框
 windowOnload: function(){
    
    
	  var that=this;
	  window.onload=function(){
    
    
		   that.load.onmouseenter();
		   if(getCookie('name')){
    
    
			    that.page2.style.opacity=1;
			    that.page2.style.zIndex=1;
			    that.wrapper.style.opacity=0;
			    that.wrapper.style.zIndex=0;
		   }else{
    
    
			   if(getCookie('remMe')=='true'){
    
    
				     that.remember.checked=true;
				     that.te2.value=getCookie('username');
				     that.pa2.value=getCookie('password');
				     that.te2.style.color="#000";
				     that.pa2.style.color="#000";
		           }else if(getCookie('remMe')=='false'){
    
    
				     if(getCookie('auto')=='false'){
    
    
					      SetCookie("username","",-1);
					      SetCookie("password","",-1);
				     }
			    }
		            if(getCookie('auto')=='true'){
    
    
				     that.remember1.checked=true;
				     that.te2.value=getCookie('username');
				     that.pa2.value=getCookie('password');
				     that.te2.style.color="#000";
				     that.pa2.style.color="#000";
				     setTimeout(function(){
    
    
					      if(that.remember1.checked== "true"){
    
    
					          SetCookie("name","true",30);
					          that.page2.style.opacity=1;
					          that.page2.style.zIndex=1;
					          that.wrapper.style.opacity=0;
					          that.wrapper.style.zIndex=0;
					      }
				    },500);
			     }else{
    
    
                                   if(getCookie('remMe')=='false'){
    
    
				      SetCookie("username","",-1);
				      SetCookie("password","",-1);
				     }
		             }
	         }
	 }
}

2.只使用cookie,NodeJs中设置cookie,前端js删除cookie
分析:
不要忘记,纯在js中编写cookie显然是极不安全的。因此我改进了一下方案一
(1)每次点击确定登录按钮后,ajax发送给后台的用户信息中携带上"check=…&check1=…"。check为记住密码的状态,值为true或者false,check1为自动登录的状态,值同check。然后在NodeJs后台进行check值与check的判断以及用户名和密码的判断,如果登录成功,倘若check与check1值均为false,删除用户名和密码的cookie,倘若check为true或者check1位true,设置用户名和密码的cookie。同时设置remMe,auto,name这三个cookie。
(2)同方案一中的分析(2),函数实现也与方案一中的 windowOnload函数相同。

部分代码如下:

//NodeJs实现分析(1)
//查询--->这里使用了MySql数据库
function select(name){
    
    
 //异步
     var p=new Promise(function(resolve,reject){
    
    
            var sql='SELECT test_name,test_pass FROM websites WHERE test_name=?';
            var f=[];
            f.push(name);
            connection.query(sql,f,function(err,result){
    
    
                  if(err){
    
    
                           console.log('[SELECT ERROR]-',err.message);
                  }else{
    
    
			    var dataString=JSON.stringify(result);
			    var data=JSON.parse(dataString);
			    console.log('data[0]为: ',data[0]);
			    resolve(data[0]);
	          }
	 }
      })
     return p;
}
//关于登录----->GET
server.use('/login',function(req,res){
    
    
	 var name=req.query['name'];
	 var pass=req.query['pass'];
	 var check=req.query['check'];
	 var check1=req.query['check1'];
	 //1.检查用户名不存在
	 //2.判断用户密码是否正确
	 var test=select(name);
	 var users;
	 test.then(function(data){
    
    
	     users=data;
	     //我们希望它返回的值users={name:"222",pass:"333",check:0}
	     console.log('登陆用户信息为: ',users);
	     if(users==undefined){
    
    
	         res.send({
    
    ok:false,msg:"该用户不存在"});
	     }else if(users["test_pass"]!=pass){
    
    
	         res.send({
    
    ok:false,msg:"用户或者密码错误"});
	     }else{
    
    
	           if(check=='true'||check1=='true'){
    
    
	               res.cookie('username',name,{
    
    path:'/',maxAge:1000*3600*24});
	               res.cookie('password',pass,{
    
    path:'/',maxAge:1000*3600*24});
	            }else if(check=='false'&&check1=='false'){
    
    
	               res.cookie('username',name,{
    
    path:'/',maxAge:-1});
	               res.cookie('password',pass,{
    
    path:'/',maxAge:-1});
	            }
	            res.cookie('name',"true",{
    
    path:'/',maxAge:1000*3600*24*30});
	            res.cookie('remMe',check,{
    
    path:'/',maxAge:1000*3600*24});
	            res.cookie('auto',check1,{
    
    path:'/',maxAge:1000*3600*24});
	            res.send({
    
    ok:true,msg:"登录成功"});
	    }
     })
})
//退出------>GET
server.use('/quit',function(req,res){
    
    
    res.clearCookie('name');
    res.send('登出成功。重定向的事让前端做');
})

3.cookie与seesion都使用。NodeJs中设置cookie中只保存用户名,session中保存完整的用户名及用户密码

分析:
一般来说,用户密码这种隐私的信息最好不要直接暴露在前端页面,我们可以继续改进方案二,将完整用户信息保存在session中。
(1)在点击确认登录按钮后,NodeJs判断倘若登录是否成功,如果登录成功,check为true或者check1为true,设置一个user对象,属性为username和password,保存用户名和密码放在session中。并且设置用户名username这个cookie。check和check1均为false,则删除username这个cookie,删除req.session.user这个session中的对象。同时设置记住密码check,自动登录check1,登录状态name这三个相应的cookie。
(2)刷新界面时,如果这两个cookie:check为true或者check1为true则发送一个ajax请求取得req.session.user.password。将这一值放入密码的input框中,同时将cookie名为username的值放入用户名的input框中。
遇到的问题:
分析(2)中的在刷新界面的同时发送ajax请求总是难以实现,每次刷新界面之后的密码input框中总是无值。因此这一方案的代码并未完成。

3.补充:cookie跨域的解决

cookie是存储在客户端的,我们即使在后台NodeJs中设置了
res.header("Access-Control-Allow-Origin","*");也只能实现ajax跨域而无法实现ajax跨域的同时携带cookie一起过来。如何解决这一问题呢?

  • 前端JS写ajax请求时
    xhr.open('get',url,true);
    //支持cookie跨域 3
    xhr.withCredentials = true;
    xhr.send(null);
  • NodeJs中
server.use('*',function(req,res,next){
    
    
     //支持cookie跨域 1
     res.header("Access-Control-Allow-Origin",req.headers.origin);
     //支持cookie跨域 2
     res.header("Access-Control-Allow-Credentials",true);
     res.header("Access-Control-Allow-Headers","Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild");
     res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
     next();
})

猜你喜欢

转载自blog.csdn.net/qq_44875145/article/details/104393987