用户/登录模块

时间:2011-09-06 04:27:45

标签: php zend-framework

我正在尝试构建一个可以在大多数Web应用程序中使用的用户模块,我使用zend-framework来构建它,到目前为止我已经完成了以下工作:

用户和访问控制相关表

用户

user_id (int 11 auto increment PK)
username (varchar 50 unique)
password (varchar 25)
email (varchar 50)
created_on (datetime)
updated-on (datetime)
lastvisit (datetime)
status (boolean default 1) 

作用

role_id (int 11 auto increment PK)
role_name (varchar 25 unique)
description (varchar 100) 

USER_ROLE

user_id (int 11 foreign key to user table)
role_id (int 11 foreign key to role table) 

user_reset

reset_id (int 11 auto increment PK)
user_email (varchar 50)
uniqid(varchar 20)
reset_flag (tinyint 1) 

控制器和操作

UserControllers

  • registerAction
  

user_status设置为零

  • enableUserAction
  

启用用户uri将通过电子邮件发送,user_status发送到一个

  • forgotPasswordAction

  • 则loginAction

  • resetPasswordAction

  • editInfoAction

  • changePasswordAction

  • accountInfoAction

  • disableAccountAction

  • logoutAction

模型,逻辑和DbInteraction图层

类UserTable()

方法

  • 保存($ data)
  • 更新($ data,$ condition,$ value)
  • fetch($ fields,$ condition,$ value)
  • 删除($ condition,$ value)
  • getUserById($ UID)
  • getUserByEmail($电子邮件)

类用户()

  • 验证(大多数验证都是使用zend库完成的)
    • 电子邮件验证
    • 用户名验证(复制,字符数)
    • 密码验证等......

方法:

  • user_emailNotification
  

@params toEmail String

     

{电子邮件设置,电子邮件模板,发送邮件}

  • user_authentication
  

@params用户名| emalilAddress String,String

     

返回布尔值

  • user_checkUniqueEmail
  

@params email String

     

返回布尔值

  • user_checkResetFlag
  

@params email String

     

返回布尔值

我正在努力使这个模块尽可能重用,所以我很乐意收到关于类结构,数据库/表结构或任何有关模块的任何建议,以使其更加模块化。所以,如果您有任何建议,请发布。

1 个答案:

答案 0 :(得分:3)

我认为你的模型很好,我唯一要改变的是你的USerTable类并将它分成两个独立的类:

  • 管理与数据持久性服务(您的数据库,但也可能是Web服务)的低级别交互的类
  • 一个类似于这个的表,它管理登录的业务规则,但是它调用刚刚提到的低级别类(如委托)来实现真正的数据访问/持久性。

使用此系统,如果您更改存储用户数据的方式,则无需重写您的UserTable doe,并且每个类只有一个责任。

但据我猜测,你用纯文本存储你的密码(25个字符不足以用于md5或sha *)。您应该不这样做:在您的数据库中,将您的密码列编辑为至少64个字符长。

然后使用带有salt的强哈希来存储密码(例如sha256,这是一个示例):

<?php
 define('SALT', 'myVery53cr3tpA55w0rd!');
 //I assume the password is already defined
 $pass =  hash('sha256',SALT.$pass);

这是最低限度的。您可以对密码执行多个哈希循环以使其更强大,或使用某些框架来管理密码安全性,例如phpass

这有点偏离主题,但有太多被黑网站的明文密码丢失了

希望有所帮助! 本杰明

编辑:以下是UserTable分离的一些准则:

主要目标是拥有一个包含业务模型和操作的业务类,而不管用于存储和获取数据的系统。此类将为每个数据持久性服务使用特定的“存储”适配器。

这个类看起来像这样:

<?php
class UserManager
{
    private $adapter; 


public function __construct($adapter)
{
    $this->adapter = $adapter; 
}

public function save($user)
{
    if ($this->adapter->userExists()) {
        return false;
    }
    try {
        $this->adapter->save($user);
    } catch(Exception $e) {
        //Log or do whatever you want with the exception
        return false;
    }
    return true;
}

public function deleteUser($user)
{
    if(!$this->adapter->userExists()) {
        throw new Exception ("User : ".$user->getName()." does not exists");
    }
}

//add all required operations here (fetching all users, finding a user,...) 
}

此类执行管理用户所需的所有操作,但它需要一个负责实际数据操作的适配器,并且将依赖于底层数据存储服务。让我们首先创建一个接口,以便能够管理多个数据存储服务:

<?php
interface UserStorageAdapterInterface
{
public function save(User $user);
public function delete(User $user);
public function userExists(User $user);
/** TO be continued **/
}

当我们使用RDBMS,NoSQL或Web服务进行数据存储时,此接口允许我们确保适配器将包含使用UserManager所需的方法。

然后,我们可以为当前的RDBMS实现一个特定的类:

<?php
Class UserStorageAdapterPDO implements  UserStorageAdapterInterface
{
private $dbAdapter;
public function __construct($dbAdapter)
{
    $this->dbAdapter = $sbAdapter;
}

public function userExists(User $user)
{
    $sql = "SELECT COUNT * FROM user WHERE user_id = ".(int)$user->getId().";";
    $rs = $dbAdapter->fetchAll($sql);
    if($rs[0]!= 0) {
        return true;
    }
    return false;
}
}

我们现在可以为Soap webservice实现另一个类:

<?php
Class UserStorageAdapterSoap implements  UserStorageAdapterInterface
{
private $soapClient;
public function __construct($soapClient)
{
    $this->soapClient = $soapClient;
}

public function userExists(User $user)
{
    $rs = $this->soapClient->userExists($user);
    if($rs === 1) {
        return true;
    }
    return false;
}
}

这种架构增加了一小部分复杂性,但为您带来了几个好处:

  • 可测试性:您只需要模拟适配器以测试用户管理的业务规则
  • 关注点分离:使用此架构,您可以更新存储适配器,而无需担心业务模式不会受到影响
  • 可扩展性:如果您的下一个应用程序之一使用了Nosql数据库(例如),则可以轻松创建新的存储适配器,而无需扩展或重写Manager类,这可能会导致更多错误,更多代码将被重写。

对你来说更清楚吗?如果没有,请告诉我:)