喜悦国际村 
» 游客:  注册 | 登录 | 搜索 | 统计 | 喜悦证交所 | 帮助

RSS 订阅当前论坛  

【村长请吃饭啊】 ---北京诚聘--- 【你还在犹豫吗?】

上一主题 下一主题
     
标题: [经验] php登陆验证之方案  
 
gaoshikao
新手上路
Rank: 1



UID 82076
精华 0
积分 25
帖子 20
金钱 25 喜悦币
威望 0
人脉 0
阅读权限 10
注册 2006-10-24
状态 离线
php登陆验证之方案

每个步入php学习的人,我想最开始接触的东西就是用户的登陆验证以及状态更新了,我也一直在被这个问题困扰,难道就没有安全的人性化的解决办法嘛?

如果仅仅用cookie,则难以保证有效的安全;如果仅仅用session,难以保证用户的持久登陆,我觉得最持久最安全的办法是session+cookie+数据库。在这一方面,我对discuz的做法很佩服,我觉得它的验证是一个非常完美的解决方案。

先说下cookie的特点:存放在客户端,可以人为改变,不安全
再说下session的特点:关闭浏览器则退出登陆,持久性不好

那么discuz就是把三者有机的结合在一起,保证安全,准确,持久。在客户端存放sid,auth这两个信息。sid是sessionid的简写,其实就是表XX_sessioins的sid,auth是一个认证字符串,它是经过加过密的,只要authkey不被公布,能保证足够的安全性。客户端的这两个值都可以改变(因为是存放在cookie里的吗),但是只要不同时改变,那么就可以通过其中的一个而自动更新另一个,否则,如果都改变,那么就退出登陆了。在这个基础上,理解以下代码就非常容易了。

<?php
if($sid) {
    if(
$discuz_uid) {
        
$query $db->query("SELECT s.sid, s.styleid, s.groupid='6' AS ipbanned, s.pageviews AS spageviews, s.lastolupdate, s.seccode, $membertablefields
            FROM {$tablepre}sessions s, {$tablepre}members m
            WHERE m.uid=s.uid AND s.sid='$sid' AND CONCAT_WS('.',s.ip1,s.ip2,s.ip3,s.ip4)='$onlineip' AND m.uid='$discuz_uid'
            AND m.password='$discuz_pw' AND m.secques='$discuz_secques'"
);
    } else {
        
$query $db->query("SELECT sid, uid AS sessionuid, groupid, groupid='6' AS ipbanned, pageviews AS spageviews, styleid, lastolupdate, seccode
            FROM {$tablepre}sessions WHERE sid='$sid' AND CONCAT_WS('.',ip1,ip2,ip3,ip4)='$onlineip'"
);
    }
    if(
$_DSESSION $db->fetch_array($query)) {
        
$sessionexists 1;
        if(!empty(
$_DSESSION['sessionuid'])) {
            
$query $db->query("SELECT $membertablefields
                FROM {$tablepre}members m WHERE uid='$_DSESSION[sessionuid]'"
);
            
$_DSESSION array_merge($_DSESSION$db->fetch_array($query));
        }
    } else {
        
$query $db->query("SELECT sid, groupid, groupid='6' AS ipbanned, pageviews AS spageviews, styleid, lastolupdate, seccode
            FROM {$tablepre}sessions WHERE sid='$sid' AND CONCAT_WS('.',ip1,ip2,ip3,ip4)='$onlineip'"
);
        if(
$_DSESSION $db->fetch_array($query)) {
            
clearcookies();
            
$sessionexists 1;
        }
    }
}

if(!
$sessionexists) {
    if(
$discuz_uid) {
        
$query $db->query("SELECT $membertablefields, m.styleid
            FROM {$tablepre}members m WHERE m.uid='$discuz_uid' AND m.password='$discuz_pw' AND m.secques='$discuz_secques'"
);
        if(!(
$_DSESSION $db->fetch_array($query))) {
            
clearcookies();
        }
    }
    if(
ipbanned($onlineip)) $_DSESSION['ipbanned'] = 1;

    
$_DSESSION['sid'] = random(6);
    
$_DSESSION['seccode'] = random(61);
}
?>
我在这里只给出构思,大家可以慢慢理解。那么discuz是如何做到更新用户状态的呢?是通过一个updatesession函数,这个函数在每次非ajax页面都是执行,入口是footer.htm的{eval updatesession();}

关于和登陆有关的其他设置,我就不详细说明了。

我的一点理解,若有纰漏,希望大家指正。
2008-2-19 11:29 AM#1
查看资料  发短消息  顶部
 
sanshi0815 (sanshi0815)
高级会员
Rank: 4
中级会员



UID 63534
精华 1
积分 533
帖子 669
金钱 523 喜悦币
威望 10
人脉 0
阅读权限 50
注册 2005-3-18
状态 离线
[推荐阅读] 希望大家推荐本好书
这个好是好,但是你既然用cookie了,那为什么不把用户名,id,还有其他需要的信息同时加密,保存.这样以后应用要简单的多!可以参考wind
这个模式如果你要扩展一个你的模块而使用dz的用户系统,那就比较麻烦了,因为我们不光是用uid,同时用户名,我们也需要,其他的,我们基本都不关心了,那个时候这个就麻烦了,别管操作什么样的表,只要是频繁,那自然就会有压力,但是就为了取个用户名,如此操作,那就比较累了
2008-3-4 09:20 AM#2
查看资料  Blog  发短消息  QQ  顶部
 
gaoshikao
新手上路
Rank: 1



UID 82076
精华 0
积分 25
帖子 20
金钱 25 喜悦币
威望 0
人脉 0
阅读权限 10
注册 2006-10-24
状态 离线
[推荐阅读] 求MYSQL管理安全/优化方面的书籍
回复 #2 sanshi0815 的帖子

不是啊,discuz的加密字符串是加密uid,username的,通过sid和authkey就可以获取他们,如果想获取更多的信息,可以在sql语句里添加啊,而且我想如果真的需要更多的信息的话,提取一次也是值得的.
2008-3-13 02:28 PM#3
查看资料  发短消息  顶部
 
scf2
注册会员
Rank: 2
中级会员



UID 19294
精华 0
积分 195
帖子 210
金钱 195 喜悦币
威望 0
人脉 0
阅读权限 20
注册 2003-4-1
来自 重庆人在深圳
状态 离线
[推荐阅读] 限量发行陈冠希的图片
一直在寻找比较好的解决方案



傲客网,找你想要的......
http://oklrc.com
2008-3-14 09:42 PM#4
查看资料  访问主页  发短消息  QQ  顶部
     


  可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题 | 开通个人空间  


 


Powered by Discuz! 6.1.0  © 2001-2010 Comsenz Inc.
Processed in 0.024832 second(s), 6 queries

(冀ICP备05009913号) 管理员:sadly 邮箱/MSN: sadly@phpx.com QQ:824008(长隐) 清除 Cookies - - Archiver - WAP