自己修改的ko3 auth module,增加了非orm方式的auth驱动

oldha 2 年之前

modules\auth\classes\auth\database.php

<?php defined('SYSPATH') OR die('No direct access allowed.');


class Auth_Database extends Kohana_Auth_Database {}

modules\auth\classes\kohana\auth\database.php

<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
 * ORM Auth driver.
 *
 * $Id: database.php 4335 2009-12-23 10:21:02 Hutchin $
 *
 * @package    Auth
 * @author     Hutchin
 * @copyright  (c) 2009-2010 Hutchin
 * @license    http://kohanaphp.com/license.html
 */
class Kohana_Auth_Database extends Auth {


	/**
	 * Checks if a session is active.
	 *
	 * @param   string   role name
	 * @param   array    collection of role names
	 * @return  boolean
	 */
	public function logged_in($role = NULL)
	{
		$status = FALSE;


		// Get the user from the session
		$user = $this->session->get($this->config['session_key']);
		
		if (is_array($user) AND $user['id'] > 0)
		{
			// Everything is okay so far
			$status = TRUE;


			if ( ! empty($role))
			{
				// If role is an array
				if (is_array($role))
				{
					// Check each role
					foreach ($role as $role_iteration)
					{
						if ( ! is_array($role_iteration))
						{
							$role_iteration = DB::select('id','name')
								->from('roles')
								->where('name','=',$role_iteration)
								->execute()
								->get_first();
						}
						$count = DB::select(DB::expr('COUNT(*) AS mycount'))
							->from('roles_users')
							->where('role_id', '=', $role_iteration['id'])
							->and_where('user_id', '=', $user['id'])
							->execute()
							->get('mycount');
						// If the user doesn't have the role
						if( ! $count )
						{
							// Set the status false and get outta here
							$status = FALSE;
							break;
						}
					}
				}
				else
				{
					// Else just check the one supplied roles
					if ( ! is_array($role))
					{
						// Load the role
						$role = DB::select('id','name')
							->from('roles')
							->where('name','=',$role)
							->execute()
							->get_first();
					}


					// Check that the user has the given role
					$status = DB::select(DB::expr('COUNT(*) AS mycount'))
							->from('roles_users')
							->where('role_id', '=', $role['id'])
							->andwhere('user_id', '=', $user['id'])
							->execute()
							->get('mycount');
				}
			}
		}


		return $status;
	}


	/**
	 * Logs a user in.
	 *
	 * @param   string   username
	 * @param   string   password
	 * @param   boolean  enable auto-login
	 * @return  boolean
	 */
	public function _login($user, $password, $remember)
	{
		if ( ! is_array($user))
		{
			// Load the user
			$user = DB::select('id','username','password','email','logins','last_login')
				->from('users')
				->where($this->config['login_key'],'=',$user)
				->execute()
				->get_first();
		}


		$role = DB::select('id','name')
			->from('roles')
			->where('name','=','login')
			->execute()
			->get_first();


		$user_has_role = DB::select(DB::expr('COUNT(*) AS mycount'))
				->from('roles_users')
				->where('role_id', '=', $role['id'])
				->and_where('user_id', '=', $user['id'])
				->execute()
				->get('mycount');


		// If the passwords match, perform a login
		if ($user_has_role AND $user['password'] === $password)
		{
			if ($remember === TRUE)
			{
				$token = $this->create_token();
				// Create a new autologin token
				DB::insert('tokens_users', array('user_id','expires','user_agent','created','token'))
					->values(array($user['id'], time() + $this->config['lifetime'], sha1(Request::$user_agent), time(),$token))
					->execute();


				// Set the autologin cookie
				cookie::set('authautologin', $token, $this->config['lifetime']);
			}


			// Finish the login
			$this->complete_login($user);


			return TRUE;
		}


		// Login failed
		return FALSE;
	}


	/**
	 * Forces a user to be logged in, without specifying a password.
	 *
	 * @param   mixed    username
	 * @return  boolean
	 */
	public function force_login($user)
	{
		if ( ! is_array($user))
		{
			// Load the user
			$user = DB::select('id','username','password','email','logins','last_login')
				->from('users')
				->where($this->config['login_key'],'=',$user)
				->execute()
				->get_first();
		}


		// Mark the session as forced, to prevent users from changing account information
		$this->session->set('auth_forced', TRUE);


		// Run the standard completion
		$this->complete_login($user);
	}


	/**
	 * Logs a user in, based on the authautologin cookie.
	 *
	 * @return  boolean
	 */
	public function auto_login()
	{
		if ($token = cookie::get('authautologin'))
		{
			// Load the token and user
			$token = DB::select('id','user_id','expires','user_agent','created','token')
				->from('tokens_users')
				->where('token','=',$token)
				->execute()
				->get_first();
			$user = DB::select('id','username','password','email','logins','last_login')
				->from('users')
				->where('id','=',$token['user_id'])
				->execute()
				->get_first();
			if ($token['user_id'] AND $user['id'])
			{
				if ($token['user_agent'] === sha1(Request::$user_agent))
				{
					$new_token = $this->create_token();
					// Save the token to create a new unique token
					DB::update('tokens_users')
						->set(array('token'=>$new_token))
						->where('id','=',$token['id'])
						->execute();


					// Set the new token
					cookie::set('authautologin', $new_token, $token['expires'] - time());


					// Complete the login with the found data
					$this->complete_login($user);


					// Automatic login was successful
					return TRUE;
				}
			}
		}


		return FALSE;
	}


	/**
	 * Log a user out and remove any auto-login cookies.
	 *
	 * @param   boolean  completely destroy the session
	 * @param	boolean  remove all tokens for user
	 * @return  boolean
	 */
	public function logout($destroy = FALSE, $logout_all = FALSE)
	{
		if ($token = cookie::get('authautologin'))
		{
			// Delete the autologin cookie to prevent re-login
			cookie::delete('authautologin');


			// Clear the autologin token from the database
			$token = DB::select('id','user_id','expires','user_agent','created','token')
				->from('tokens_users')
				->where('token','=',$token)
				->execute()
				->get_first();


			if ($token['id'] AND $logout_all)
			{
				DB::delete('tokens_users')
					->where('user_id', '=', $token['user_id'])
					->execute();
			}
			elseif ($token['id'])
			{
				DB::delete('tokens_users')
					->where('id', '=', $token['id'])
					->execute();
			}
		}


		return parent::logout($destroy);
	}


	/**
	 * Get the stored password for a username.
	 *
	 * @param   mixed   username
	 * @return  string
	 */
	public function password($user)
	{
		if ( ! is_array($user))
		{
			// Load the user
			$user = DB::select('id','username','password','email','logins','last_login')
				->from('users')
				->where($this->config['login_key'],'=',$user)
				->execute()
				->get_first();;
		}


		return $user['password'];
	}


	/**
	 * Complete the login for a user by incrementing the logins and setting
	 * session data: user_id, username, roles
	 *
	 * @param   object   user model object
	 * @return  void
	 */
	protected function complete_login($user)
	{
		$total_rows = DB::update('users')
			->set(array('logins'=>$user['logins'] + 1, 'last_login'=>time()))
			->where('id','=',$user['id'])
			->execute();


		return parent::complete_login($user);
	}


	/**
	 * Finds a new unique token, using a loop to make sure that the token does
	 * not already exist in the database. This could potentially become an
	 * infinite loop, but the chances of that happening are very unlikely.
	 *
	 * @return  string
	 */
	protected function create_token()
	{
		while (TRUE)
		{
			// Create a random token
			$token = text::random('alnum', 32);


			// Make sure the token does not already exist
			$count = DB::select('id')
				->where('token', '=', $token)
				->from('tokens_users')
				->execute()
				->count();


			if ($count === 0)
			{
				// A unique token has been found
				return $token;
			}
		}
	}
} // End Auth_Database_Driver

在config中设置'driver' => 'Database',就可正常使用

返回的user模型为数组

HOHO,既然用到了数据库,一般人应该也离不开 ORM 的吧?

据我了解orm似乎需要mysql的innodb引擎支持,但我只想用myisam引擎,所以改了下

我觉得innodb引擎蛮好,外键功能蛮好。呵呵

呃。没有强制需要的,是不是你的哪里没有调试好。

目前本论坛的数据库表是纯 MyISAM 引擎的..

哦?那可能真的是我没调试好,不知道orm需要外键支持不?
如果是需要的话只能用innodb引擎了,

另外,我做的项目是查询量大,而insert,update不多,所以用myisam还是不错的,
查询中有很多sql语句非常复杂,没办法用orm去完成,还是手写的sql效率高些,呵呵.

不管怎么说,经过我的补充,auth已经很完整了,可以不依赖orm扩展就可以运行

ORM 不涉及数据库引擎的,数据库逻辑是大部分支持的,因为 Database 支持 PDO 的,所以并不存在“专政”一个数据库的。

看来是我误会orm了,不过orm的效率到底是不太高,还是自己写的sql来的更快

发表讨论

在回复之前你需要先进行登录
记住我的登录状态 (忘记密码)