PHP网站中保持登录状态的功能是怎么做的?

WBOY
Release: 2016-06-06 16:42:10
Original
8055 people have browsed it

大多数网站在用户登录时会提供一个“记住我”或者“保持登录状态”的选项,我只知道是用Cookie实现的,但是具体来说的工作流程是什么?因为要实现一个网站登录的东西,所以想从细节方面了解这个问题。

回复内容:

我来谈谈这个问题吧
首先,基于以上几位朋友提到的,SESSION信息存储在服务端,相对于存储在客户端的COOKIE更为安全,所以正常一般网站在用于“判断用户是否登录”时,确实是使用SESSION,例如可以在SESSION里存储如下一个数组
<code class="language-php"><span class="x">//验证用户名和密码成功后</span>
<span class="x">$_SESSION['userinfo'] = [</span>
<span class="x">  'uid' => 123,</span>
<span class="x">  'username' => 'testuser'</span>
<span class="x">];</span>
</code>
Copy after login
PHP中有cookie相关的函数, 用户登录成功的时候,可能有如下的语句:
setcookie("user", "user1", time()+3600);

判断用户是否登录的时候,有类似这样的语句:
if (isset($_COOKIE["user"])){
echo "已经登录";
}

用户退出的时候,有类似这样的语句:
setcookie("user", "", time()-3600);

如果用户登录后一直没点退出按钮,3600秒之后,cookie也会失效。
如果想让用户保持足够长的时间 time()+3600*24*365 就是登录后一年内都有效。 看具体需求了,如果是本地记住那就直接用Cookie,把用户名等信息存起来,这就够了。如果是一段时间内任何地方免登录那就用Session存在服务器。然后当你访问网站时直接判断cookie或者session是否存在有效的登录信息。当然为了安全,你可以通过一些加密手段将用户信息加密之后再存储起来。 前面说的用user name作为session标识,存用户数据每次请求从session取数据到数据库校验,都是错误的做法。
第一个做法完全避免不了构造请求获取用户数据,也做不到灵活使用session,没有登录的就没有session数据?
第二个做法完全误用session的作用,如果拿了session存的用户帐号还要去数据库取数据,那session存用户帐号完全无意义。
此外退出浏览器并不会自动删除网站cookie数据,非主动清除的情况下cookie的有效期是根据set cookie的超时时间值确定的,超时才会清理。

1、sessionid是怎么生成的,在接收请求之后,就需要判断cookie是否提交sessionid参数,不存在则生成一个标识通过set cookie通知浏览器记录sessionid。同时以此sessionid为标识存浏览器会话状态所需的数据在服务器。
这个操作与是否登录无关。任何请求都可设置这个操作。用于标识浏览器与服务器的会话状态。

2、如何实现记录用户登录状态,通常会在登录校验之后在cookie失效时间上面下功夫,而不是将用户名密码用任何形式存储在客户端或客户端。比如在1步的情况下,set cookie通知浏览器此cookie失效时间为一个月,同时服务端的缓存记录登录状态,失效时间也设置成一个月。

这样只要浏览器不清理cookie,每一个请求服务端的参数都会自动把cookie里面存的sessionid提交给服务端,这样服务端可以通过get_session_info(sessionid)获取会话状态的敏感数据,比如登录状态,用户名之类的数据。这样就实现了登录状态的保存。

3、不建议做的事情
不建议在浏览器前端做任何记录用户个人信息的操作,存个标识即可。
不建议在取session数据的时候做任何读取数据库的操作,使用session的目的就是把浏览器会话所需的数据缓存,避免读取数据库。
不建议使用单个sessionid作为标识,像 左岸 的回答一样,使用至少一个随机字符串作为校验标识,避免sessionid撞库。 各位大虾好,我是只是说我自己的理解....

如果只用cookie的话貌似也可以实现登录功能,不过一般都是用session来实现登录吧?

在php中session_start之后就会产生一个session文件,一般放在tmp目录中,同时会设置一个客户端的cookie,而这个cookie的值,其实就是随机产生的session id,这样一次会话也就建立了

这样每次发送http请求的时候,服务器就将cookie中获得session id和那个session的文件内容关联起来了,php的程序中也就可以通过超级全局变量$_SESSION来获得session信息了

不过到目前为止,还只是一次会话的建立,不算是用户登录,一般意义上的登录应该指的是把当前用户的信息和此次会话关联起来,在php中一般就是,先通过用户提交的用户名和密码进行验证,将衍生后的信息给$_SESSION赋值

我觉得这样就是一次登录的过程吧,大概整理一下是:

1.session start 建立会话
2.通过用户发送的用户名密码进行验证,验证成功则将用户信息与会话关联

会话的建立让服务器始终知道这些请求是同一个用户,用户登录是让服务器知道这一直是哪一个用户

究其原因还是因为http本身是无状态协议,所以应用程序本身就要在两头保存一些信息进行状态的确认

各位大虾,一直以来我就是这么实现的登录,自己也不知道有没有什么问题,如果有问题的话大侠们一定要指出啊,尤其是安全方面的

这样省得我以后犯更严重的错误 COOKIE由于存储在客户端,有被随意篡改的风险,所以其实服务器判断用户登陆状态,一般都是用SESSION的...SESSION的数据存储在服务器中,但是必须通过客户端的COOKIE来找到对应的SESSION
所以用户登录的过程实际上是
1:用户输入用户名密码,POST数据到服务器
2:服务器判断用户名密码是否正确,若正确,则在客户端创建一个存储SESSION_ID的COOKIE,并且在服务器中创建一个相对应的SESSION_ID的SESSION,SESSION里面的数据可能为用户的数据
3:以后该用户进行操作时,先从客户端取出SESSION_ID,找到服务器相对应的SESSION,取出数据,进行校验后再进行下一步操作..
然后说说我理解的保持登陆状态
由于COOKIE存储在客户端,所以不建议用isset($_COOKIE['username'])来判断用户是否登陆.
因为用户完全可以伪造一个COOKIE,来达到欺骗服务器的目的...
那么,我想到的两种方法是:
1:上面有人说了,存储username和加密的密码,再次访问时,服务器取出COOKIE数据,与数据库做校对,如果通过,则判断为已经登陆
2:建立一个MySQL表,里面存cookie_id,username,expire,time,然后每次登陆时,根据用户选择保存登陆时间,来生成一个md5加密的cookie_id(可以用username,时间戳和随机数生成),然后将cookie_id,username,用户保持的登陆时间,当前时间戳一起插入数据库中,并且创建一个名为cookieid,值为上述md5加密的cookie_id的COOKIE.
那么下一次用户访问时,服务器可以先取COOKIE,根据COOKIE里的cookieid找到相对应的数据库中的数据,判断有无合法COOKIE,有无生命周期等...如果全部通过就能判定为登陆了...
以上纯为个人见解,如有不妥,请指教 先说说结论:
1.cookie和session都可以用来保持登录状态。
2.如果使用cookie,用于保存用户状态的cookie需要加密,并且可被识别,但不必须可以解密。这个意思就是说,加密后的存储了用户登录信息的cookie数据在服务端可被还原,即使不能还原也要可以用于识别和比对(即唯一),php的加密函数可以去网上找,一搜一大把。
3.如果使用session,在不考虑安全的情况下,可以简单的使用$_SESSION这个全局数组达到目的,但是如果需要更高的安全性,需要额外的参数进行安全性验证,可以是加密字符串也可以是某串数据的MD5指纹。
4.使用session可以保证登录数据的一致性,如果登录数据中有在登录时间内可能会发生变动的项目,但是依然需要用到额外的参数去提取原来的session数据。
5.cookie比起session会有个滞后性,这一点需要注意,有时候有益,有时候也不方便。
6.在完全理解session的工作机制后,可以尝试抛弃php本身的session机制,建立自定义session机制。

终极结论:
为了保证安全性,既然都需要加密cookie,那么,为什么不把用户登录数据都存储在cookie里呢?session还会浪费服务器端存储。

终极进阶结论:
当你学会使用内存数据库的时候,比如memcached或者redis之类的,cookie和它们结合才是绝佳的解决方案。

下面扯点别的:

说起状态维持这件事情,一直是http的痛处,因为http是无状态协议,要让无状态协议支持状态维持,于是产生了cookie,早期浏览器对cookie戒心甚大,于是勉为其难用一下GET参数也是无妨,现代浏览器都是默认开启cookie的,甚至大部分都已经支持了浏览器端存储(storage)以及少部分支持了浏览器端数据库,后两者仅是存储,在请求时并不会向服务器反馈数据。而session是建立在cookie或者其他从浏览器传回的数据之上的,脱离了cookie或者其他从浏览器传回的参数(比如GET参数)就是无源之水、无根之木。
有人说,甚至有不少人说,session比cookie安全,我觉得这是不恰当的看法。cookie和session具有同等的安全性,并不会因为cookie存储于客户端而session存储于服务端而使cookie的安全性低于session,可以这么说,cookie和session的安全性都取决于cookie或者前文提到的传回服务器的参数的安全性。
而且session也不仅仅是局限于php本身提供的session库,任何存储于服务器端的数据都有可能扮演session的角色,本质上session是一种特殊的数据库,只不过这个数据库只允许已被识别的唯一合法客户端去访问。
虽然我在上面一段文字中强调了唯一,但是识别过程并不可靠,也就是有可能不唯一,这就是所谓的不安全性的来源。事实上,自从网络诞生以来,其上一直充斥的欺骗与暴力。这世上没有任何事情是唯一的,就像没有任何事物是完全相同的,虽然哲学一直教导我们世界上没有两件完全一样的事物,也没有两件完全独立的事物,但是这种绝对的观念并不适合相对的生活。生活中,存在唯一这个概念,然而令人遗憾的是并没有唯一的事实。即使有个枕边人温言细语的告诉你,你是他的唯一,如果你真信了,那只能是你太天真。唯一这个事情是有分辨粒度的,在可被识别的范围内,唯一才是有意义的,但是这种有意义却着实令人心碎,可识别意味着判断一个事物是否唯一的规则是有限的,有限就意味着可仿冒,时至今日,人类创造了各种用于识别唯一性的技术,但是关于识别技术,却依然在发展,而且永无止境。

最后的最后,附赠几段cookie操作函数:
特性1:去除了cookie的延时性,即设即用。
特性2:可以很方便的在cookie中存储数组,不需要一条条的写setcookie语句。
特性3:支持“.”索引,比如test.aaaa.bbbb是指cookie里的test[aaaa][bbbb]。
注意1:千万小心cookie的4kb限制,虽然有的现代浏览器可能扩充了这个限制。
注意2:cookie里存太多东西毕竟增加了网络数据传输以及服务器的数据处理。

<code class="language-php"><span class="x">function set_cookie($data,$path = '/',$time = 0,$doma = NULL)</span>
<span class="x">{</span>
<span class="x">	if(!is_array($data))</span>
<span class="x">	{</span>
<span class="x">		$para = func_get_args();</span>
<span class="x">		$data = array($para[0] => $para[1]);</span>
<span class="x">		$path = isset($para[2]) ? $para[2] : '/';</span>
<span class="x">		$time = isset($para[3]) ? $para[3] : 0;</span>
<span class="x">		$doma = isset($para[4]) ? $para[4] : NULL;</span>
<span class="x">	}</span>

<span class="x">	if(is_int($path))</span>
<span class="x">	{</span>
<span class="x">		$time = $path;</span>
<span class="x">		$path = '/';</span>
<span class="x">	}</span>

<span class="x">	if(is_string($time))</span>
<span class="x">	{</span>
<span class="x">		$doma = $time;</span>
<span class="x">		$time = 0;</span>
<span class="x">	}</span>

<span class="x">	$time = $time == 0 ? $time : time()+$time;</span>

<span class="x">	foreach($data as $key => $value)</span>
<span class="x">	{</span>
<span class="x">		if(!is_array($value))</span>
<span class="x">		{</span>
<span class="x">			if(strpos($key,'.') === FALSE)</span>
<span class="x">			{</span>
<span class="x">				if(isset($_COOKIE[$key]))</span>
<span class="x">				{</span>
<span class="x">					if(is_array($_COOKIE[$key]))</span>
<span class="x">					{</span>
<span class="x">						$cookie_str = http_build_query(array($key => $_COOKIE[$key]));</span>
<span class="x">						$cookie_arr = explode('&',$cookie_str);</span>

<span class="x">						foreach($cookie_arr as $cookie)</span>
<span class="x">						{</span>
<span class="x">							$a_cookie = explode('=',$cookie);</span>
<span class="x">							setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);</span>
<span class="x">						}</span>

<span class="x">						$_COOKIE[$key] = NULL;</span>
<span class="x">					}</span>
<span class="x">				}</span>

<span class="x">				setcookie($key,$value,$time,$path,$doma);</span>

<span class="x">				$_COOKIE[$key] = $value;</span>
<span class="x">			}</span>
<span class="x">			else</span>
<span class="x">			{</span>
<span class="x">				$cop = &$_COOKIE;</span>
<span class="x">				$cox = substr_count($key,'.');</span>

<span class="x">				foreach(explode('.',$key) as $ckk => $ckey)</span>
<span class="x">				{</span>
<span class="x">					if($ckk > 0)</span>
<span class="x">					{</span>
<span class="x">						$cookie_key .= '['.$ckey.']';</span>
<span class="x">					}</span>
<span class="x">					else</span>
<span class="x">					{</span>
<span class="x">						$cookie_key = $ckey;</span>
<span class="x">					}</span>

<span class="x">					if($ckk 
<span class="x">					{</span>
<span class="x">						if(isset($cop[$ckey]))</span>
<span class="x">						{</span>
<span class="x">							if(!is_array($cop[$ckey]))</span>
<span class="x">							{</span>
<span class="x">								setcookie($cookie_key,NULL,-1,$path,$doma);</span>

<span class="x">								$cop[$ckey] = NULL;</span>
<span class="x">							}</span>
<span class="x">						}</span>
<span class="x">						else</span>
<span class="x">						{</span>
<span class="x">							$cop[$ckey] = NULL;</span>
<span class="x">						}</span>

<span class="x">						$cop = &$cop[$ckey];</span>
<span class="x">					}</span>
<span class="x">					else</span>
<span class="x">					{</span>
<span class="x">						if(isset($cop[$ckey]))</span>
<span class="x">						{</span>
<span class="x">							if(is_array($cop[$ckey]))</span>
<span class="x">							{</span>
<span class="x">								$cookie_str = http_build_query(array($cookie_key => $cop[$ckey]));</span>
<span class="x">								$cookie_arr = explode('&',$cookie_str);</span>

<span class="x">								foreach($cookie_arr as $cookie)</span>
<span class="x">								{</span>
<span class="x">									$a_cookie = explode('=',$cookie);</span>
<span class="x">									setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);</span>
<span class="x">								}</span>

<span class="x">								$cop[$ckey] = NULL;</span>
<span class="x">							}</span>
<span class="x">						}</span>
<span class="x">						else</span>
<span class="x">						{</span>
<span class="x">							$cop[$ckey] = NULL;</span>
<span class="x">						}</span>

<span class="x">						$cop = &$cop[$ckey];</span>
<span class="x">					}</span>
<span class="x">				}</span>

<span class="x">				setcookie($cookie_key,$value,$time,$path,$doma);</span>

<span class="x">				$cop = $value;</span>
<span class="x">			}</span>
<span class="x">		}</span>
<span class="x">		else</span>
<span class="x">		{</span>
<span class="x">			$x_cookie_str = http_build_query($value);</span>
<span class="x">			$x_cookie_arr = explode('&',$x_cookie_str);</span>

<span class="x">			foreach($x_cookie_arr as $x_cookie)</span>
<span class="x">			{</span>
<span class="x">				$a_cookie = explode('=',$x_cookie);</span>

<span class="x">				if(isset($a_cookie[1]))</span>
<span class="x">				{</span>
<span class="x">					set_cookie($key.'.'.str_replace(array('[',']'),array('.',''),urldecode($a_cookie[0])),urldecode($a_cookie[1]),$time,$path,$doma);</span>
<span class="x">				}</span>
<span class="x">			}</span>
<span class="x">		}</span>
<span class="x">	}</span>
<span class="x">}</span>

<span class="x">function cookie($key = NULL,$def = FALSE)</span>
<span class="x">{</span>
<span class="x">	if(!empty($key))</span>
<span class="x">	{</span>
<span class="x">		if(strpos($key,'.') === FALSE)</span>
<span class="x">		{</span>
<span class="x">			if(isset($_COOKIE[$key]))</span>
<span class="x">			{</span>
<span class="x">				return $_COOKIE[$key];</span>
<span class="x">			}</span>
<span class="x">			else</span>
<span class="x">			{</span>
<span class="x">				return $def;</span>
<span class="x">			}</span>
<span class="x">		}</span>
<span class="x">		else</span>
<span class="x">		{</span>
<span class="x">			$cop = &$_COOKIE;</span>

<span class="x">			foreach(explode('.',$key) as $ckey)</span>
<span class="x">			{</span>
<span class="x">				if(isset($cop[$ckey]))</span>
<span class="x">				{</span>
<span class="x">					$cop = &$cop[$ckey];</span>
<span class="x">				}</span>
<span class="x">				else</span>
<span class="x">				{</span>
<span class="x">					return $def;</span>
<span class="x">				}</span>
<span class="x">			}</span>

<span class="x">			return $cop;</span>
<span class="x">		}</span>
<span class="x">	}</span>
<span class="x">	else</span>
<span class="x">	{</span>
<span class="x">		return $_COOKIE;</span>
<span class="x">	}</span>
<span class="x">}</span>

<span class="x">function unset_cookie($key = NULL,$path = '/',$doma = NULL)</span>
<span class="x">{</span>
<span class="x">	if(!empty($key))</span>
<span class="x">	{</span>
<span class="x">		if(strpos($key,'.') === FALSE)</span>
<span class="x">		{</span>
<span class="x">			if(isset($_COOKIE[$key]))</span>
<span class="x">			{</span>
<span class="x">				if(!is_array($_COOKIE[$key]))</span>
<span class="x">				{</span>
<span class="x">					setcookie($key,NULL,-1,$path,$doma);</span>
<span class="x">				}</span>
<span class="x">				else</span>
<span class="x">				{</span>
<span class="x">					$cookie_str = http_build_query(array($key => $_COOKIE[$key]));</span>
<span class="x">					$cookie_arr = explode('&',$cookie_str);</span>

<span class="x">					foreach($cookie_arr as $cookie)</span>
<span class="x">					{</span>
<span class="x">						$a_cookie = explode('=',$cookie);</span>
<span class="x">						setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);</span>
<span class="x">					}</span>
<span class="x">				}</span>

<span class="x">				unset($_COOKIE[$key]);</span>
<span class="x">			}</span>
<span class="x">		}</span>
<span class="x">		else</span>
<span class="x">		{</span>
<span class="x">			$cop = &$_COOKIE;</span>
<span class="x">			$ckeys = explode('.',$key);</span>
<span class="x">			$pop_ckey = array_pop($ckeys);</span>

<span class="x">			foreach($ckeys as $ckk => $ckey)</span>
<span class="x">			{</span>
<span class="x">				if($ckk > 0)</span>
<span class="x">				{</span>
<span class="x">					$cookie_key .= '['.$ckey.']';</span>
<span class="x">				}</span>
<span class="x">				else</span>
<span class="x">				{</span>
<span class="x">					$cookie_key = $ckey;</span>
<span class="x">				}</span>

<span class="x">				if(isset($cop[$ckey]))</span>
<span class="x">				{</span>
<span class="x">					$cop = &$cop[$ckey];</span>
<span class="x">				}</span>
<span class="x">				else</span>
<span class="x">				{</span>
<span class="x">					return;</span>
<span class="x">				}</span>
<span class="x">			}</span>

<span class="x">			if(isset($cop[$pop_ckey]))</span>
<span class="x">			{</span>
<span class="x">				if(!is_array($cop[$pop_ckey]))</span>
<span class="x">				{</span>
<span class="x">					setcookie($cookie_key.'['.$pop_ckey.']',NULL,-1,$path,$doma);</span>
<span class="x">				}</span>
<span class="x">				else</span>
<span class="x">				{</span>
<span class="x">					$cookie_str = http_build_query(array($cookie_key.'['.$pop_ckey.']' => $cop[$pop_ckey]));</span>
<span class="x">					$cookie_arr = explode('&',$cookie_str);</span>

<span class="x">					foreach($cookie_arr as $cookie)</span>
<span class="x">					{</span>
<span class="x">						$a_cookie = explode('=',$cookie);</span>
<span class="x">						setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);</span>
<span class="x">					}</span>
<span class="x">				}</span>

<span class="x">				unset($cop[$pop_ckey]);</span>
<span class="x">			}</span>
<span class="x">		}</span>
<span class="x">	}</span>
<span class="x">	else</span>
<span class="x">	{</span>
<span class="x">		if(!empty($_COOKIE))</span>
<span class="x">		{</span>
<span class="x">			$cookie_str = http_build_query($_COOKIE);</span>
<span class="x">			$cookie_arr = explode('&',$cookie_str);</span>

<span class="x">			foreach($cookie_arr as $cookie)</span>
<span class="x">			{</span>
<span class="x">				$a_cookie = explode('=',$cookie);</span>
<span class="x">				setcookie(urldecode($a_cookie[0]),NULL,-1,$path,$doma);</span>
<span class="x">			}</span>

<span class="x">			$_COOKIE = array();</span>
<span class="x">		}</span>
<span class="x">	}</span>
<span class="x">}</span>
</span></code>
Copy after login
虽然cookie和session都可以实现题主所想要的功能,但是更推荐使用session。
原因无他,只因为更安全,不容易被截获伪造登录信息。
<code class="language-php"><span class="x">// 登录成功后记录登录信息</span>
<span class="x">$_SESSION['loginStatus'] = array(</span>
<span class="x">    'username' => $username,</span>
<span class="x">    'status' => true,</span>
<span class="x">    'loginTime' = > time(),</span>
<span class="x">);</span>
<span class="x">.</span>
<span class="x">.</span>
<span class="x">.</span>
<span class="x">// 判断session信息</span>
<span class="x">if(empty($_SESSION['loginStatus']['status']) || !$_SESSION['loginStatus']['status']) {</span>
<span class="x">    // 引导到登录页</span>
<span class="x">} else {</span>
<span class="x">    // 加载用户信息</span>
<span class="x">}</span>
</code>
Copy after login
cookie和session 我记得韩顺平老师的视频里面,有一块专门教写登录模块的教程。
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!