V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
feikeq
V2EX  ›  PHP

请问一下大家平常都是怎么验证用户登录的?

  •  
  •   feikeq · 2013-02-26 17:11:42 +08:00 · 7797 次点击
    这是一个创建于 4078 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一般情况下网站都会记录用户登录成功的cookie记录,但我为了安全,用户的每一次操作我都会去和数据库验证一次,就是无论用户打开页面还是添加一条操作都会验证。这很明显加重了MYSQL查询的负担,有没有更简单有效一点的方法?
    14 条回复    1970-01-01 08:00:00 +08:00
    jybox
        2
    jybox  
       2013-02-26 17:20:05 +08:00
    我之前是这样的,数据库里面是 hash(hash(user)+hash(passwd)) 记作dbPasswd
    然后在配置文件里面写了个全局的干扰码记作cookieCode

    用户登陆后写到cookie里面的大概就是 hash(dbPasswd+cookieCode)
    然后每次刷新页面都会连接数据库验证一次,和楼主的差不多,好处就是代码很简单....写到一个类里面不过四五十行.


    正在编写中的新版网站是这样的,每次登录成功后随机生成一个字符串写入Cookie, 记作token, 存入数据库. 然后同时把当前的登录状态记入session.
    验证时如果session中已有登录状态就用session的, 没有的话再检查Cookie里的token是否在数据库中.

    这样的好处就是减少了查询数据库的次数,同时可以单独追踪和取消每个会话的授权(删掉对应的token就行).
    jybox
        3
    jybox  
       2013-02-26 17:20:53 +08:00
    我没看过太多这方面的资料...都是自己摸索出来的..可能不太成熟.
    feikeq
        4
    feikeq  
    OP
       2013-02-26 17:28:31 +08:00
    @jybox session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能....
    fork3rt
        5
    fork3rt  
       2013-02-26 17:29:29 +08:00
    SESSION
    feikeq
        6
    feikeq  
    OP
       2013-02-26 17:29:32 +08:00
    @binux 翻译过来还是云里雾里的.....
    ---------------------------------------
    会话管理

    在人机交互,会话管理的过程中,保持互动的整个会话跟踪用户的活动的计算机系统。
    在一个桌面环境中的典型会话管理任务,包括记录哪些应用程序是开放的,它记录了每个应用程序已打开,让相同的状态,当用户登录,登录后,可以恢复。对于一个网站,会话管理可能会要求用户重新登录会话已过期(即在一定期限后没有用户活动)。它也可用于将信息存储在服务器端的HTTP请求之间。
    [ 编辑 ] 桌面会话管理
    一种桌面会话管理器是一个程序,可以保存和恢复桌面会话。桌面会话是当前正在运行的所有窗口和当前的内容。基于Linux的系统上所提供的X会话管理器会话管理。在微软Windows系统中,没有会话管理器是包含在系统中,但可以提供的第三方应用程序,如twinsplay会话管理。
    [ 编辑 ] 浏览器会话管理
    会话管理是在一个Web浏览器,用户可以在其中保存所有打开的页面和设置,并恢复他们在以后的日子特别有用。为了帮助恢复系统或应用程序崩溃,也可以被还原页面和设置下运行。谷歌Chrome,OmniWeb和歌剧的Web浏览器,支持会话管理的例子。其他现代的浏览器,如Mozilla Firefox浏览器支持会话管理,通过第三方插件或扩展。会话管理往往是通过cookie的应用管理。
    [ 编辑 ] Web服务器会话管理
    超文本传输协议(HTTP)是无状态的:一个客户端计算机上运行Web浏览器与每一个新的HTTP GET或POST请求,必须建立一个新的传输控制协议(TCP)网络连接到Web服务器。该网站的服务器,因此,不能依靠已建立的TCP网络连接的时间不是一个单一的HTTP GET或POST操作。会话管理是由Web开发人员所使用的技术,使无状态的HTTP协议支持的会话状态。例如,当一个用户到Web服务器的身份验证,用户的HTTP请求(GET或POST)不应该导致Web服务器要求用户的帐号和密码。所采用的方法来完成此看到的HTTP cookie和会话ID的讨论。
    [世界上第一个会话管理系统被称为神,发明和开发的大卫Hostettler韦恩于1996年。使用Web浏览器的文字和图像应用程序被视为最好安装定制的MS-Windows的客户端或X Window的服务器,特别适用于低带宽连接。但是最初并不支持HTTP/1.0的Web 会话的所有功能。然而DHW创造一种变通方法使用会话ID,NCSA httpd的版本1.0的马赛克和Netscape的工作。整点的会话ID是整个会话状态并不需要被传递到/从客户端/服务器通过HTTP Cookie的每个交易阶段。]
    的会话信息存储在web服务器上,使用产生的作为结果的第一个(有时第一个认证。)运行Web浏览器从最终用户请求的会话标识符的会话ID。会话ID和相关联的会话的数据(用户名,账户号码等)在Web服务器上的“存储”,是通过使用各种技术,包括,但不限于,本地存储器,平面文件和数据库。
    在多个Web服务器的情况下,必须分享知识的会话状态(这是典型的在一个集群环境中)的会话信息必须正在运行Web服务器软件的群集节点之间共享。在群集的节点之间共享会话状态的方法包括:成员节点多播会话信息(见JGroups的这种技术的一个例子),与合作伙伴节点使用分布式共享内存或内存虚拟化共享的会话信息,在节点之间使用共享的会话信息网络插座,会话信息存储在一个共享的文件系统,如网络文件系统或全局文件系统,或群集之外的在数据库中存储会话信息。
    如果会话信息被认为是短暂的,不稳定的数据,并不需要交易的不可抵赖性和不包含数据(例如在美国,健康保险可携性及责任性法案,萨班斯-奥克斯利法案“合规性审计法两部法律必须遵守审计)的例子,然后可以使用任何存储会话信息的方法。但是,如果会话信息是合规性审计,应考虑给定的会话存储,复制和集群所采用的方法。
    在构建一个面向服务的架构,简单对象访问协议或SOAP消息的可扩展标记语言(XML)消息可用于消费类应用,导致Web服务器创建会话。
    binux
        7
    binux  
       2013-02-26 17:31:38 +08:00
    @feikeq 就是通过加密cookie,直接在cookie中保存,而客户端亦无法伪造
    gamexg
        8
    gamexg  
       2013-02-26 21:20:52 +08:00
    大部分系统都是 cookie 里面存放session id,然后用户相关信息放到 session 里,session 存放到 Memcached 之类的缓存上面。
    weicode
        9
    weicode  
       2013-02-26 22:13:28 +08:00
    将用户UID加密后后存入COOKIE,也就是所谓的token值。根据token解密后的UID获取用户信息,进而判断是否登录。现在有加密解密支持过期时间,比如DISCUZ加密解密函数。定期更换密钥KEY。
    这样做的弊端若用户修改密码此token还是有效的。避免XSS漏洞,可将此COOKIE设置成HTTPONLY COOKIE。
    xing393939
        10
    xing393939  
       2013-02-27 10:33:05 +08:00
    @weicode "避免XSS漏洞,可将此COOKIE设置成HTTPONLY COOKIE。" HTTPONLY COOKIE 能防止伪造么?
    raincious
        11
    raincious  
       2013-02-27 15:09:39 +08:00
    @jybox 我的方法也跟你类似,不过我还是用了每次打开页面都得找一次数据库的作法。因为我参考Discuz 6那时代的代码来构建我的Session管理器时,发现Discuz即使这样做了,速度也很快。

    但还是看负载需求吧,如果网站太大了,估计就得用Ajax配合等页面打开后读取Session然后改页面这样了估计。

    我的方法是:
    1、用户打开网页时,先检测Cookie,如果有我之前设定的Cookie,则使用那个Cookie在数据库中一个特殊的表里搜索用户等入记录,如果没有这个记录,则将用户会话标记为Guest(不给他分配用户ID)。

    2、如果找到了这个记录,通过等入记录、用户记录进行比对,如果有这个用户、而且登入可用,则将会话标记为Member(给他分配一个用户ID)

    应用程序里使用 if (MemberID) 来检测用户是否登陆过。

    如果在第一步里,用户没有发送任何Cookie,则非随机产生一个,比如可以通过IP地址什么的,然后发送这个给用户,同时启用PHP自己的Session,记录这个Cookie。

    可能说得不是很清楚,这里有源代码(Discuz 6时代构建的,一直没怎么改而且为了兼容性,写得很长),可以参考下:https://code.google.com/p/faculaframework/source/browse/trunk/include/class.session.php

    这里有使用的例子:http://test.refugeone.com/ // 除了登陆和用户管理外完全不能工作的网站
    feikeq
        12
    feikeq  
    OP
       2013-03-01 16:57:03 +08:00
    @raincious 为了 www。tibiji。com 服务器性能我最终放弃 session 这种方法,还是用cookie。
    作法是:
    1.先生成一个加密的token保存用户登录状态cookie 时间为一月或半年
    2.再生成一个根据IP地址加密码的cookie、限制时间为1天或2天

    验证方法是
    一、如果有cookie记录2号并且当前用户的IP地址相符则直接登录成功不用去数据库里验证。
    二、如果2号cookie记录与用户IP不匹配就用1号cookie去数据库里验证
    三、如果1号cookie验证通过则更新2号cookie,反之则重新让用户手动登录。


    这样就能适当给Mysql缓解查询压力了....
    jybox
        13
    jybox  
       2013-03-02 23:17:39 +08:00
    soli
        14
    soli  
       2013-04-23 10:51:05 +08:00
    没人考虑 CSRF 么?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   866 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:54 · PVG 04:54 · LAX 13:54 · JFK 16:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.