基于身份验证和级别的授权

v1.0.0-beta9 2015-11-26 03:10 UTC

README

PHP的基于身份验证和级别的授权

安装

使用composer安装

composer require jasny\auth

设置

Jasny\Auth是一个抽象类。您需要扩展它并实现抽象方法fetchUserByIdfetchUserByUsername。同时将$secret属性设置为随机选择的字符串。

您还需要指定如何在请求之间持久化当前用户。如果想要使用正常的PHP会话,可以使用Auth\Sessions特质。

class Auth extends Jasny\Auth
{
    use Auth\Sessions;

    /**
     * Secret word for creating a verification hash
     * @var string
     */
    protected static $secret = "A random string";
    

    /**
     * Fetch a user by ID
     * 
     * @param int $id
     * @return User
     */
    public static function fetchUserById($id)
    {
        // Database action that fetches a User object
    }

    /**
     * Fetch a user by username
     * 
     * @param string $username
     * @return User
     */
    public static function fetchUserByUsername($username)
    {
        // Database action that fetches a User object
    }
}

获取方法需要返回一个实现了Jasny\Auth\User接口的对象。

class User implements Jasny\Auth\User
{
    /**
     * Get the user ID
     * 
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Get the usermame
     * 
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Get the hashed password
     * 
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * Event called on login.
     * 
     * @return boolean  false cancels the login
     */
    public function onLogin()
    {
        if (!$this->active) return false;

        $this->last_login = new DateTime();
        $this->save();
        
        return true;
    }

    /**
     * Event called on logout.
     */
    public function onLogout()
    {
        $this->last_logout = new DateTime();
        $this->save();
    }
}

授权

默认情况下,Auth类只执行身份验证。可以通过实现authorize方法添加授权。

定义了两个特质用于授权:Authz\byLevelAuthz\byGroup

按级别

Authz\byLevel特质实现了基于访问级别的授权。每个用户都获得其级别和所有低于该级别的权限。

class Auth extends Jasny\Auth implements Jasny\Auth\Authorization
{
    use Jasny\Authz\byLevel;

    /**
     * Authorization levels
     * @var array
     */
    protected static $levels = [
        1 => 'user',
        10 => 'moderator',
        20 => 'admin',
        50 => 'superadmin'
    ];
}

对于授权,用户对象还需要实现Jasny\Authz\User,添加hasRole()方法。

/**
 * Check if the user has the specified security level
 * 
 * @param int $level
 * @return boolean
 */
public function hasRole($level)
{
    return $this->security_level >= $level;
}

按组

Auth\byGroup特质实现了使用访问组的授权。一个访问组可能覆盖其他组。

class Auth extends Jasny\Auth implements Jasny\Auth\Authorization
{
    use Jasny\Authz\byGroup;

    /**
     * Authorization groups and each group is supersedes.
     * @var array
     */
    protected static $groups = [
        'users' => [],
        'managers' => [],
        'employees' => ['user'],
        'developers' => ['employees'],
        'paralegals' => ['employees'],
        'lawyers' => ['paralegals'],
        'lead-developers' => ['developers', 'managers'],
        'firm-partners' => ['lawyers', 'managers']
    ];
}

对于授权,用户对象还需要实现Jasny\Authz\User,添加hasRole()方法。

/**
 * Check if the user is in the specified security group
 * 
 * @param string $group
 * @return boolean
 */
public function hasRole($group)
{
    return in_array($group, Auth::expandGroup($this->group));
}

用法

身份验证

验证用户名和密码

Auth::verify($username, $password);

使用用户名和密码登录

Auth::login($username, $password);

设置用户(不进行验证)

Auth::setUser($user);

登出

Auth::logout();

获取当前用户

Auth::user();

授权

检查用户是否有权执行某些操作

if (!Auth::authorized('admin')) die("Not allowed");

注册确认

获取一个验证散列。将其用于URL并在电子邮件中设置该URL给用户

// Create a new $user
    
$confirmHash = generateConfirmationHash($user);
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/confirm.php?hash=' . $hash;
    
// send email with $url to $user

使用确认散列获取并验证用户

// --- confirm.php

$user = Auth::fetchForConfirmation($_GET['hash']);

忘记密码

忘记密码与注册确认功能相同。

// Fetch $user by e-mail
    
$confirmHash = generatePasswordResetHash($user);
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/reset.php?hash=' . $hash;
    
// send email with $url to $user

使用确认散列获取并验证用户

// --- reset.php

$user = Auth::fetchForPasswordReset($_GET['hash']);