Commit 2dbfda65 by Qiang Xue

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

parents 6a2bfae4 7d27d65a
......@@ -238,7 +238,7 @@ class YiiBase
{
if ($path === null) {
unset(self::$aliases[$alias]);
} elseif ($path[0] !== '@') {
} elseif (strncmp($path, '@', 1)) {
self::$aliases[$alias] = rtrim($path, '\\/');
} else {
self::$aliases[$alias] = static::getAlias($path);
......
......@@ -8,6 +8,35 @@
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>
* @since 2.0
......@@ -29,8 +58,11 @@ interface Identity
public function getId();
/**
* 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.
* @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
public $flashVar = '__flash';
/**
* @var array parameter-value pairs to override default session cookie parameters
*/
public $cookieParams = array(
'httponly' => true
);
/**
* Initializes the application component.
* This method is required by IApplicationComponent and is invoked by application.
*/
......@@ -111,6 +118,8 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
);
}
$this->setCookieParams($this->cookieParams);
@session_start();
if (session_id() == '') {
......
......@@ -13,7 +13,7 @@ use yii\base\HttpException;
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.
* Through methods [[login()]] and [[logout()]], you can change the user authentication status.
......@@ -32,15 +32,6 @@ class User extends Component
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.
*/
public $identityClass;
......@@ -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.
* @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
* remains inactive. If this property is not set, the user will be logged out after
......@@ -112,8 +103,6 @@ class User extends Component
Yii::$app->getSession()->open();
$this->loadIdentity();
$this->renewAuthStatus();
if ($this->enableAutoLogin) {
......@@ -125,20 +114,44 @@ 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()
{
if ($this->_identity === false) {
$id = $this->getId();
if ($id === null) {
$this->identity = null;
$this->_identity = null;
} else {
/** @var $class Identity */
$class = $this->identityClass;
$this->identity = $class::findIdentity($id);
$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;
}
/**
* Logs in a user.
......@@ -157,10 +170,7 @@ class User extends Component
public function login($identity, $duration = 0)
{
if ($this->beforeLogin($identity, false)) {
$this->switchIdentity($identity);
if ($duration > 0 && $this->enableAutoLogin) {
$this->sendIdentityCookie($identity, $duration);
}
$this->switchIdentity($identity, $duration);
$this->afterLogin($identity, false);
}
return !$this->getIsGuest();
......@@ -185,10 +195,7 @@ class User extends Component
$identity = $class::findIdentity($id);
if ($identity !== null && $identity->validateAuthKey($authKey)) {
if ($this->beforeLogin($identity, true)) {
$this->switchIdentity($identity);
if ($this->autoRenewCookie) {
$this->sendIdentityCookie($identity, $duration);
}
$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
$this->afterLogin($identity, true);
}
} elseif ($identity !== null) {
......@@ -206,12 +213,9 @@ class User extends Component
*/
public function logout($destroySession = true)
{
$identity = $this->identity;
$identity = $this->getIdentity();
if ($identity !== null && $this->beforeLogout($identity)) {
$this->switchIdentity(null);
if ($this->enableAutoLogin) {
Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
}
if ($destroySession) {
Yii::$app->getSession()->destroy();
}
......@@ -225,7 +229,7 @@ class User extends Component
*/
public function getIsGuest()
{
return $this->identity === null;
return $this->getIdentity() === null;
}
/**
......@@ -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.
* 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.
......@@ -400,24 +396,37 @@ class User extends Component
}
/**
* Changes the current user with the specified identity information.
* This method is called by [[login()]] and [[loginByCookie()]]
* when the current user needs to be associated with the corresponding
* identity information.
* Switches to a new identity for the current user.
*
* This method will save necessary session information to keep track of the user authentication status.
* 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.
* 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->regenerateID(true);
$this->setIdentity($identity);
$session->remove($this->idVar);
$session->remove($this->authTimeoutVar);
if ($identity instanceof Identity) {
$this->setId($identity->getId());
$session->set($this->idVar, $identity->getId());
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
*/
protected function renewAuthStatus()
{
if ($this->authTimeout !== null && $this->identity !== null) {
if ($this->authTimeout !== null && !$this->getIsGuest()) {
$expire = Yii::$app->getSession()->get($this->authTimeoutVar);
if ($expire !== null && $expire < time()) {
$this->logout(false);
......
<?php
namespace yiiunit\framework\util;
namespace yiiunit\framework\helpers;
use yii\helpers\ArrayHelper;
......
<?php
namespace yiiunit\framework\util;
namespace yiiunit\framework\helpers;
use Yii;
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