Commit 2dbfda65 by Qiang Xue

Merge branch 'master' of git.yiisoft.com:yii2

parents 6a2bfae4 7d27d65a
...@@ -238,7 +238,7 @@ class YiiBase ...@@ -238,7 +238,7 @@ class YiiBase
{ {
if ($path === null) { if ($path === null) {
unset(self::$aliases[$alias]); unset(self::$aliases[$alias]);
} elseif ($path[0] !== '@') { } elseif (strncmp($path, '@', 1)) {
self::$aliases[$alias] = rtrim($path, '\\/'); self::$aliases[$alias] = rtrim($path, '\\/');
} else { } else {
self::$aliases[$alias] = static::getAlias($path); self::$aliases[$alias] = static::getAlias($path);
......
...@@ -8,6 +8,35 @@ ...@@ -8,6 +8,35 @@
namespace yii\web; namespace yii\web;
/** /**
* Identity is the interface that should be implemented by a class providing identity information.
*
* This interface can typically be implemented by a user model class. For example, the following
* code shows how to implement this interface by a User ActiveRecord class:
*
* ~~~
* class User extends ActiveRecord implements Identity
* {
* public static function findIdentity($id)
* {
* return static::find($id);
* }
*
* public function getId()
* {
* return $this->id;
* }
*
* public function getAuthKey()
* {
* return $this->authKey;
* }
*
* public function validateAuthKey($authKey)
* {
* return $this->authKey === $authKey;
* }
* }
* ~~~
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
...@@ -29,8 +58,11 @@ interface Identity ...@@ -29,8 +58,11 @@ interface Identity
public function getId(); public function getId();
/** /**
* Returns a key that can be used to check the validity of a given identity ID. * Returns a key that can be used to check the validity of a given identity ID.
* The space of such keys should be big and random enough to defeat potential identity attacks. *
* The returned key can be a string, an integer, or any serializable data. * The key should be unique for each individual user, and should be persistent
* so that it can be used to check the validity of the user identity.
*
* The space of such keys should be big enough to defeat potential identity attacks.
* *
* This is required if [[User::enableAutoLogin]] is enabled. * This is required if [[User::enableAutoLogin]] is enabled.
* @return string a key that is used to check the validity of a given identity ID. * @return string a key that is used to check the validity of a given identity ID.
......
...@@ -60,6 +60,13 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -60,6 +60,13 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
public $flashVar = '__flash'; public $flashVar = '__flash';
/** /**
* @var array parameter-value pairs to override default session cookie parameters
*/
public $cookieParams = array(
'httponly' => true
);
/**
* Initializes the application component. * Initializes the application component.
* This method is required by IApplicationComponent and is invoked by application. * This method is required by IApplicationComponent and is invoked by application.
*/ */
...@@ -111,6 +118,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co ...@@ -111,6 +118,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
); );
} }
$this->setCookieParams($this->cookieParams);
@session_start(); @session_start();
if (session_id() == '') { if (session_id() == '') {
......
...@@ -13,7 +13,7 @@ use yii\base\HttpException; ...@@ -13,7 +13,7 @@ use yii\base\HttpException;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
/** /**
* User is an application component that manages the user authentication status. * User is the class for the "user" application component that manages the user authentication status.
* *
* In particular, [[User::isGuest]] returns a value indicating whether the current user is a guest or not. * In particular, [[User::isGuest]] returns a value indicating whether the current user is a guest or not.
* Through methods [[login()]] and [[logout()]], you can change the user authentication status. * Through methods [[login()]] and [[logout()]], you can change the user authentication status.
...@@ -32,15 +32,6 @@ class User extends Component ...@@ -32,15 +32,6 @@ class User extends Component
const EVENT_AFTER_LOGOUT = 'afterLogout'; const EVENT_AFTER_LOGOUT = 'afterLogout';
/** /**
* @var Identity the identity object associated with the currently logged user.
* This property is set automatically be the User component. Do not modify it directly
* unless you understand the consequence. You should normally use [[login()]], [[logout()]],
* or [[switchIdentity()]] to update the identity associated with the current user.
*
* If this property is null, it means the current user is a guest (not authenticated).
*/
public $identity;
/**
* @var string the class name of the [[identity]] object. * @var string the class name of the [[identity]] object.
*/ */
public $identityClass; public $identityClass;
...@@ -65,7 +56,7 @@ class User extends Component ...@@ -65,7 +56,7 @@ class User extends Component
* @var array the configuration of the identity cookie. This property is used only when [[enableAutoLogin]] is true. * @var array the configuration of the identity cookie. This property is used only when [[enableAutoLogin]] is true.
* @see Cookie * @see Cookie
*/ */
public $identityCookie = array('name' => '__identity'); public $identityCookie = array('name' => '__identity', 'httponly' => true);
/** /**
* @var integer the number of seconds in which the user will be logged out automatically if he * @var integer the number of seconds in which the user will be logged out automatically if he
* remains inactive. If this property is not set, the user will be logged out after * remains inactive. If this property is not set, the user will be logged out after
...@@ -112,8 +103,6 @@ class User extends Component ...@@ -112,8 +103,6 @@ class User extends Component
Yii::$app->getSession()->open(); Yii::$app->getSession()->open();
$this->loadIdentity();
$this->renewAuthStatus(); $this->renewAuthStatus();
if ($this->enableAutoLogin) { if ($this->enableAutoLogin) {
...@@ -125,19 +114,43 @@ class User extends Component ...@@ -125,19 +114,43 @@ class User extends Component
} }
} }
private $_identity = false;
/** /**
* Loads the [[identity]] object according to [[id]]. * Returns the identity object associated with the currently logged user.
* @return Identity the identity object associated with the currently logged user.
* Null is returned if the user is not logged in (not authenticated).
* @see login
* @see logout
*/ */
protected function loadIdentity() public function getIdentity()
{ {
$id = $this->getId(); if ($this->_identity === false) {
if ($id === null) { $id = $this->getId();
$this->identity = null; if ($id === null) {
} else { $this->_identity = null;
/** @var $class Identity */ } else {
$class = $this->identityClass; /** @var $class Identity */
$this->identity = $class::findIdentity($id); $class = $this->identityClass;
$this->_identity = $class::findIdentity($id);
}
} }
return $this->_identity;
}
/**
* Sets the identity object.
* This method should be mainly be used by the User component or its child class
* to maintain the identity object.
*
* You should normally update the user identity via methods [[login()]], [[logout()]]
* or [[switchIdentity()]].
*
* @param Identity $identity the identity object associated with the currently logged user.
*/
public function setIdentity($identity)
{
$this->_identity = $identity;
} }
/** /**
...@@ -157,10 +170,7 @@ class User extends Component ...@@ -157,10 +170,7 @@ class User extends Component
public function login($identity, $duration = 0) public function login($identity, $duration = 0)
{ {
if ($this->beforeLogin($identity, false)) { if ($this->beforeLogin($identity, false)) {
$this->switchIdentity($identity); $this->switchIdentity($identity, $duration);
if ($duration > 0 && $this->enableAutoLogin) {
$this->sendIdentityCookie($identity, $duration);
}
$this->afterLogin($identity, false); $this->afterLogin($identity, false);
} }
return !$this->getIsGuest(); return !$this->getIsGuest();
...@@ -185,10 +195,7 @@ class User extends Component ...@@ -185,10 +195,7 @@ class User extends Component
$identity = $class::findIdentity($id); $identity = $class::findIdentity($id);
if ($identity !== null && $identity->validateAuthKey($authKey)) { if ($identity !== null && $identity->validateAuthKey($authKey)) {
if ($this->beforeLogin($identity, true)) { if ($this->beforeLogin($identity, true)) {
$this->switchIdentity($identity); $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
if ($this->autoRenewCookie) {
$this->sendIdentityCookie($identity, $duration);
}
$this->afterLogin($identity, true); $this->afterLogin($identity, true);
} }
} elseif ($identity !== null) { } elseif ($identity !== null) {
...@@ -206,12 +213,9 @@ class User extends Component ...@@ -206,12 +213,9 @@ class User extends Component
*/ */
public function logout($destroySession = true) public function logout($destroySession = true)
{ {
$identity = $this->identity; $identity = $this->getIdentity();
if ($identity !== null && $this->beforeLogout($identity)) { if ($identity !== null && $this->beforeLogout($identity)) {
$this->switchIdentity(null); $this->switchIdentity(null);
if ($this->enableAutoLogin) {
Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
}
if ($destroySession) { if ($destroySession) {
Yii::$app->getSession()->destroy(); Yii::$app->getSession()->destroy();
} }
...@@ -225,7 +229,7 @@ class User extends Component ...@@ -225,7 +229,7 @@ class User extends Component
*/ */
public function getIsGuest() public function getIsGuest()
{ {
return $this->identity === null; return $this->getIdentity() === null;
} }
/** /**
...@@ -238,14 +242,6 @@ class User extends Component ...@@ -238,14 +242,6 @@ class User extends Component
} }
/** /**
* @param string|integer $value the unique identifier for the user. If null, it means the user is a guest.
*/
public function setId($value)
{
Yii::$app->getSession()->set($this->idVar, $value);
}
/**
* Returns the URL that the user should be redirected to after successful login. * Returns the URL that the user should be redirected to after successful login.
* This property is usually used by the login action. If the login is successful, * This property is usually used by the login action. If the login is successful,
* the action should read this property and use it to redirect the user browser. * the action should read this property and use it to redirect the user browser.
...@@ -400,24 +396,37 @@ class User extends Component ...@@ -400,24 +396,37 @@ class User extends Component
} }
/** /**
* Changes the current user with the specified identity information. * Switches to a new identity for the current user.
* This method is called by [[login()]] and [[loginByCookie()]] *
* when the current user needs to be associated with the corresponding * This method will save necessary session information to keep track of the user authentication status.
* identity information. * If `$duration` is provided, it will also send out appropriate identity cookie
* to support cookie-based login.
*
* This method is mainly called by [[login()]], [[logout()]] and [[loginByCookie()]]
* when the current user needs to be associated with the corresponding identity information.
*
* @param Identity $identity the identity information to be associated with the current user. * @param Identity $identity the identity information to be associated with the current user.
* If null, it means switching to be a guest.
* @param integer $duration number of seconds that the user can remain in logged-in status.
* This parameter is used only when `$identity` is not null.
*/ */
protected function switchIdentity($identity) public function switchIdentity($identity, $duration = 0)
{ {
Yii::$app->getSession()->regenerateID(true);
$this->identity = $identity;
$session = Yii::$app->getSession(); $session = Yii::$app->getSession();
$session->regenerateID(true);
$this->setIdentity($identity);
$session->remove($this->idVar); $session->remove($this->idVar);
$session->remove($this->authTimeoutVar); $session->remove($this->authTimeoutVar);
if ($identity instanceof Identity) { if ($identity instanceof Identity) {
$this->setId($identity->getId()); $session->set($this->idVar, $identity->getId());
if ($this->authTimeout !== null) { if ($this->authTimeout !== null) {
Yii::$app->getSession()->set($this->authTimeoutVar, time() + $this->authTimeout); $session->set($this->authTimeoutVar, time() + $this->authTimeout);
}
if ($duration > 0 && $this->enableAutoLogin) {
$this->sendIdentityCookie($identity, $duration);
} }
} elseif ($this->enableAutoLogin) {
Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
} }
} }
...@@ -429,7 +438,7 @@ class User extends Component ...@@ -429,7 +438,7 @@ class User extends Component
*/ */
protected function renewAuthStatus() protected function renewAuthStatus()
{ {
if ($this->authTimeout !== null && $this->identity !== null) { if ($this->authTimeout !== null && !$this->getIsGuest()) {
$expire = Yii::$app->getSession()->get($this->authTimeoutVar); $expire = Yii::$app->getSession()->get($this->authTimeoutVar);
if ($expire !== null && $expire < time()) { if ($expire !== null && $expire < time()) {
$this->logout(false); $this->logout(false);
......
<?php <?php
namespace yiiunit\framework\util; namespace yiiunit\framework\helpers;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
......
<?php <?php
namespace yiiunit\framework\util; namespace yiiunit\framework\helpers;
use Yii; use Yii;
use yii\helpers\Html; use yii\helpers\Html;
......
<?php
namespace yiiunit\framework\helpers;
use \yii\helpers\StringHelper as StringHelper;
/**
* StringHelperTest
*/
class StringHelperTest extends \yii\test\TestCase
{
public function testStrlen()
{
$this->assertEquals(4, StringHelper::strlen('this'));
$this->assertEquals(6, StringHelper::strlen('это'));
}
public function testSubstr()
{
$this->assertEquals('th', StringHelper::substr('this', 0, 2));
$this->assertEquals('э', StringHelper::substr('это', 0, 2));
}
public function testPluralize()
{
$testData = array(
'move' => 'moves',
'foot' => 'feet',
'child' => 'children',
'human' => 'humans',
'man' => 'men',
'staff' => 'staff',
'tooth' => 'teeth',
'person' => 'people',
'mouse' => 'mice',
'touch' => 'touches',
'hash' => 'hashes',
'shelf' => 'shelves',
'potato' => 'potatoes',
'bus' => 'buses',
'test' => 'tests',
'car' => 'cars',
);
foreach($testData as $testIn => $testOut) {
$this->assertEquals($testOut, StringHelper::pluralize($testIn));
$this->assertEquals(ucfirst($testOut), ucfirst(StringHelper::pluralize($testIn)));
}
}
public function testCamel2words()
{
$this->assertEquals('Camel Case', StringHelper::camel2words('camelCase'));
$this->assertEquals('Lower Case', StringHelper::camel2words('lower_case'));
$this->assertEquals('Tricky Stuff It Is Testing', StringHelper::camel2words(' tricky_stuff.it-is testing... '));
}
public function testCamel2id()
{
$this->assertEquals('post-tag', StringHelper::camel2id('PostTag'));
$this->assertEquals('post_tag', StringHelper::camel2id('PostTag', '_'));
$this->assertEquals('post-tag', StringHelper::camel2id('postTag'));
$this->assertEquals('post_tag', StringHelper::camel2id('postTag', '_'));
}
public function testId2camel()
{
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag'));
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_'));
$this->assertEquals('PostTag', StringHelper::id2camel('post-tag'));
$this->assertEquals('PostTag', StringHelper::id2camel('post_tag', '_'));
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment