Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
83da0cd0
Commit
83da0cd0
authored
Apr 06, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored authentication filters.
parent
12cd71d7
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
280 additions
and
92 deletions
+280
-92
rest.md
docs/guide/rest.md
+29
-12
CHANGELOG.md
framework/CHANGELOG.md
+1
-0
classes.php
framework/classes.php
+5
-4
RateLimiter.php
framework/filters/RateLimiter.php
+18
-5
AuthInterface.php
framework/filters/auth/AuthInterface.php
+2
-2
AuthMethod.php
framework/filters/auth/AuthMethod.php
+65
-0
CompositeAuth.php
framework/filters/auth/CompositeAuth.php
+76
-0
HttpBasicAuth.php
framework/filters/auth/HttpBasicAuth.php
+55
-8
HttpBearerAuth.php
framework/filters/auth/HttpBearerAuth.php
+19
-8
QueryParamAuth.php
framework/filters/auth/QueryParamAuth.php
+3
-4
Controller.php
framework/rest/Controller.php
+7
-49
No files found.
docs/guide/rest.md
View file @
83da0cd0
...
...
@@ -599,30 +599,48 @@ There are different ways to send an access token:
server and sent to the API server via
[
HTTP Bearer Tokens
](
http://tools.ietf.org/html/rfc6750
)
,
according to the OAuth2 protocol.
Yii supports all of the above authentication methods
and can be further extended to support other
methods.
Yii supports all of the above authentication methods
. You can also easily create new authentication
methods.
To enable authentication for your APIs, do the following two steps:
1.
Configure
[
[yii\rest\Controller::authMethods
]
] with the authentication methods you plan to use.
1.
Specify which authentication methods you plan to use by configuring the
`auth`
behavior
in your REST controller classes.
2.
Implement
[
[yii\web\IdentityInterface::findIdentityByAccessToken()
]
] in your
[
[yii\web\User::identityClass|user identity class
]
].
For example, to enable all three authentication methods explained above, you would configure
`authMethods`
as follows,
For example, to enable all three authentication methods explained above, you can configure
`auth`
like following,
```
php
class
UserController
extends
ActiveController
public
function
behaviors
()
{
public
$authMethods
=
[
'yii\rest\HttpBasicAuth'
,
'yii\rest\QueryParamAuth'
,
'yii\rest\HttpBearerAuth'
,
];
return
array_merge
(
parent
::
behaviors
(),
[
'auth'
=>
[
'authMethods'
=>
[
\yii\filters\auth\HttpBasicAuth
::
className
(),
\yii\filters\auth\QueryParamAuth
::
className
(),
\yii\filters\auth\HttpBearerAuth
::
className
(),
],
],
]);
}
```
Each element in
`authMethods`
should be an auth class name or a configuration array. An auth class
Each element in
`authMethods`
should be an auth
method
class name or a configuration array. An auth class
must implement
[
[yii\rest\AuthInterface
]
].
If you only want to a single authentication method, such as HTTP Basic Auth, you may use the following code:
```
php
public
function
behaviors
()
{
return
array_merge
(
parent
::
behaviors
(),
[
'auth'
=>
[
'class'
=>
\yii\filters\auth\HttpBasicAuth
::
className
(),
],
]);
}
```
Implementation of
`findIdentityByAccessToken()`
is application specific. For example, in simple scenarios
when each user can only have one access token, you may store the access token in an
`access_token`
column
in the user table. The method can then be readily implemented in the
`User`
class as follows,
...
...
@@ -713,7 +731,6 @@ public function behaviors()
{
return
array_merge
(
parent
::
behaviors
(),
[
'rateLimiter'
=>
[
'class'
=>
\yii\filters\RateLimiter
::
className
(),
'enableRateLimitHeaders'
=>
false
,
],
]);
...
...
framework/CHANGELOG.md
View file @
83da0cd0
...
...
@@ -290,6 +290,7 @@ Yii Framework 2 Change Log
-
New: Added
`yii\codeception\DbTestCase`
(qiangxue)
-
New: Added
`yii\web\GroupUrlRule`
(qiangxue)
-
New: Added
`yii\filters\RateLimiter`
(qiangxue)
-
New: Added various authentication methods, including
`HttpBasicAuth`
,
`HttpBearerAuth`
,
`QueryParamAuth`
, and
`CompositeAuth`
(qiangxue)
2.
0.0-alpha, December 1, 2013
-----------------------------
...
...
framework/classes.php
View file @
83da0cd0
...
...
@@ -185,15 +185,16 @@ return [
'yii\requirements\YiiRequirementChecker'
=>
YII_PATH
.
'/requirements/YiiRequirementChecker.php'
,
'yii\rest\Action'
=>
YII_PATH
.
'/rest/Action.php'
,
'yii\rest\ActiveController'
=>
YII_PATH
.
'/rest/ActiveController.php'
,
'yii\rest\AuthInterface'
=>
YII_PATH
.
'/rest/AuthInterface.php'
,
'yii\rest\Controller'
=>
YII_PATH
.
'/rest/Controller.php'
,
'yii\rest\CreateAction'
=>
YII_PATH
.
'/rest/CreateAction.php'
,
'yii\rest\DeleteAction'
=>
YII_PATH
.
'/rest/DeleteAction.php'
,
'yii\rest\HttpBasicAuth'
=>
YII_PATH
.
'/rest/HttpBasicAuth.php'
,
'yii\rest\HttpBearerAuth'
=>
YII_PATH
.
'/rest/HttpBearerAuth.php'
,
'yii\rest\IndexAction'
=>
YII_PATH
.
'/rest/IndexAction.php'
,
'yii\rest\OptionsAction'
=>
YII_PATH
.
'/rest/OptionsAction.php'
,
'yii\rest\QueryParamAuth'
=>
YII_PATH
.
'/rest/QueryParamAuth.php'
,
'yii\filters\auth\CompositeAuth'
=>
YII_PATH
.
'/filters/auth/CompositeAuth.php'
,
'yii\filters\auth\AuthInterface'
=>
YII_PATH
.
'/filters/auth/AuthInterface.php'
,
'yii\filters\auth\HttpBasicAuth'
=>
YII_PATH
.
'/filters/auth/HttpBasicAuth.php'
,
'yii\filters\auth\HttpBearerAuth'
=>
YII_PATH
.
'/filters/auth/HttpBearerAuth.php'
,
'yii\filters\auth\QueryParamAuth'
=>
YII_PATH
.
'/filters/auth/QueryParamAuth.php'
,
'yii\filters\RateLimitInterface'
=>
YII_PATH
.
'/filters/RateLimitInterface.php'
,
'yii\filters\RateLimiter'
=>
YII_PATH
.
'/filters/RateLimiter.php'
,
'yii\rest\Serializer'
=>
YII_PATH
.
'/rest/Serializer.php'
,
...
...
framework/filters/RateLimiter.php
View file @
83da0cd0
...
...
@@ -40,18 +40,26 @@ use yii\web\TooManyRequestsHttpException;
class
RateLimiter
extends
ActionFilter
{
/**
* @var boolean whether to include rate limit headers in the response
*/
public
$enableRateLimitHeaders
=
true
;
/**
* @var string the message to be displayed when rate limit exceeds
*/
public
$errorMessage
=
'Rate limit exceeded.'
;
/**
* @var RateLimitInterface the user object that implements the RateLimitInterface.
* If not set, it will take the value of `Yii::$app->user->getIdentity(false)`.
*/
public
$user
;
/**
* @var
boolean whether to include rate limit headers in the response
* @var
Request the current request. If not set, the `request` application component will be used.
*/
public
$
enableRateLimitHeaders
=
true
;
public
$
request
;
/**
* @var
string the message to be displayed when rate limit exceeds
* @var
Response the response to be sent. If not set, the `response` application component will be used.
*/
public
$
errorMessage
=
'Rate limit exceeded.'
;
public
$
response
;
/**
...
...
@@ -62,7 +70,12 @@ class RateLimiter extends ActionFilter
$user
=
$this
->
user
?
:
Yii
::
$app
->
getUser
()
->
getIdentity
(
false
);
if
(
$user
instanceof
RateLimitInterface
)
{
Yii
::
trace
(
'Check rate limit'
,
__METHOD__
);
$this
->
checkRateLimit
(
$user
,
Yii
::
$app
->
getRequest
(),
Yii
::
$app
->
getResponse
(),
$action
);
$this
->
checkRateLimit
(
$user
,
$this
->
request
?
:
Yii
::
$app
->
getRequest
(),
$this
->
response
?
:
Yii
::
$app
->
getResponse
(),
$action
);
}
elseif
(
$user
)
{
Yii
::
info
(
'Rate limit skipped: "user" does not implement RateLimitInterface.'
);
}
else
{
...
...
framework/
rest
/AuthInterface.php
→
framework/
filters/auth
/AuthInterface.php
View file @
83da0cd0
...
...
@@ -5,7 +5,7 @@
* @license http://www.yiiframework.com/license/
*/
namespace
yii\
rest
;
namespace
yii\
filters\auth
;
use
yii\web\User
;
use
yii\web\Request
;
...
...
@@ -14,7 +14,7 @@ use yii\web\IdentityInterface;
use
yii\web\UnauthorizedHttpException
;
/**
* AuthInterface is the interface
required by classes that support user authentication
.
* AuthInterface is the interface
that should be implemented by auth method classes
.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
framework/filters/auth/AuthMethod.php
0 → 100644
View file @
83da0cd0
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\filters\auth
;
use
Yii
;
use
yii\base\ActionFilter
;
use
yii\web\UnauthorizedHttpException
;
use
yii\web\User
;
use
yii\web\Request
;
use
yii\web\Response
;
/**
* AuthMethod is a base class implementing the [[AuthInterface]] interface.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract
class
AuthMethod
extends
ActionFilter
implements
AuthInterface
{
/**
* @var User the user object representing the user authentication status. If not set, the `user` application component will be used.
*/
public
$user
;
/**
* @var Request the current request. If not set, the `request` application component will be used.
*/
public
$request
;
/**
* @var Response the response to be sent. If not set, the `response` application component will be used.
*/
public
$response
;
/**
* @inheritdoc
*/
public
function
beforeAction
(
$action
)
{
$identity
=
$this
->
authenticate
(
$this
->
user
?
:
Yii
::
$app
->
getUser
(),
$this
->
request
?
:
Yii
::
$app
->
getRequest
(),
$this
->
response
?
:
Yii
::
$app
->
getResponse
()
);
if
(
$identity
!==
null
)
{
return
true
;
}
else
{
$this
->
handleFailure
(
$this
->
response
?
:
Yii
::
$app
->
getResponse
());
return
false
;
}
}
/**
* @inheritdoc
*/
public
function
handleFailure
(
$response
)
{
throw
new
UnauthorizedHttpException
(
'You are requesting with an invalid credential.'
);
}
}
framework/filters/auth/CompositeAuth.php
0 → 100644
View file @
83da0cd0
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\filters\auth
;
use
Yii
;
use
yii\base\InvalidConfigException
;
/**
* CompositeAuth is an action filter that supports multiple authentication methods at the same time.
*
* The authentication methods contained by CompositeAuth are configured via [[authMethods]],
* which is a list of supported authentication class configurations.
*
* The following example shows how to support three authentication methods:
*
* ```php
* public function behaviors()
* {
* return [
* 'compositeAuth' => [
* 'class' => \yii\filters\auth\CompositeAuth::className(),
* 'authMethods' => [
* \yii\filters\auth\HttpBasicAuth::className(),
* \yii\filters\auth\QueryParamAuth::className(),
* ],
* ],
* ];
* }
* ```
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
CompositeAuth
extends
AuthMethod
{
/**
* @var array the supported authentication methods. This property should take a list of supported
* authentication methods, each represented by an authentication class or configuration.
* If this is not set or empty, no authentication will be performed.
*
* Note that an auth method class must implement the [[\yii\filters\auth\AuthInterface]] interface.
*/
public
$authMethods
=
[];
/**
* @inheritdoc
*/
public
function
authenticate
(
$user
,
$request
,
$response
)
{
foreach
(
$this
->
authMethods
as
$i
=>
$auth
)
{
$this
->
authMethods
[
$i
]
=
$auth
=
Yii
::
createObject
(
$auth
);
if
(
!
$auth
instanceof
AuthInterface
)
{
throw
new
InvalidConfigException
(
get_class
(
$auth
)
.
' must implement yii\filters\auth\AuthInterface'
);
}
$identity
=
$auth
->
authenticate
(
$user
,
$request
,
$response
);
if
(
$identity
!==
null
)
{
return
$identity
;
}
}
if
(
!
empty
(
$this
->
authMethods
))
{
/** @var AuthInterface $auth */
$auth
=
reset
(
$this
->
authMethods
);
$auth
->
handleFailure
(
$response
);
}
return
null
;
}
}
framework/
rest
/HttpBasicAuth.php
→
framework/
filters/auth
/HttpBasicAuth.php
View file @
83da0cd0
...
...
@@ -5,36 +5,83 @@
* @license http://www.yiiframework.com/license/
*/
namespace
yii\
rest
;
namespace
yii\
filters\auth
;
use
Yii
;
use
yii\base\Component
;
use
yii\web\UnauthorizedHttpException
;
/**
* HttpBasicAuth implements the HTTP Basic authentication method.
* HttpBasicAuth is an action filter that supports the HTTP Basic authentication method.
*
* You may use HttpBasicAuth by attaching it as a behavior to a controller or module, like the following:
*
* ```php
* public function behaviors()
* {
* return [
* 'basicAuth' => [
* 'class' => \yii\filters\auth\HttpBasicAuth::className(),
* ],
* ];
* }
* ```
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
HttpBasicAuth
extends
Component
implements
AuthInterface
class
HttpBasicAuth
extends
AuthMethod
{
/**
* @var string the HTTP authentication realm
*/
public
$realm
=
'api'
;
/**
* @var callable a PHP callable that will authenticate the user with the HTTP basic auth information.
* The callable receives a username and a password as its parameters. It should return an identity object
* that matches the username and password. Null should be returned if there is no such identity.
*
* The following code is a typical implementation of this callable:
*
* ```php
* function ($username, $password) {
* return \app\models\User::find([
* 'username' => $username,
* 'password' => $password,
* ]);
* }
* ```
*
* If this property is not set, the username information will be considered as an access token
* while the password information will be ignored. The [[\yii\web\User::loginByAccessToken()]]
* method will be called to authenticate and login the user.
*/
public
$auth
;
/**
* @inheritdoc
*/
public
function
authenticate
(
$user
,
$request
,
$response
)
{
if
((
$accessToken
=
$request
->
getAuthUser
())
!==
null
)
{
$identity
=
$user
->
loginByAccessToken
(
$accessToken
);
if
(
$identity
!==
null
)
{
$username
=
$request
->
getAuthUser
();
$password
=
$request
->
getAuthPassword
();
if
(
$this
->
auth
)
{
if
(
$username
!==
null
||
$password
!==
null
)
{
$identity
=
call_user_func
(
$this
->
auth
,
$username
,
$password
);
if
(
$identity
!==
null
)
{
$user
->
setIdentity
(
$identity
);
}
else
{
$this
->
handleFailure
(
$response
);
}
return
$identity
;
}
$this
->
handleFailure
(
$response
);
}
elseif
(
$username
!==
null
)
{
$identity
=
$user
->
loginByAccessToken
(
$username
);
if
(
$identity
===
null
)
{
$this
->
handleFailure
(
$response
);
}
return
$identity
;
}
return
null
;
...
...
framework/
rest
/HttpBearerAuth.php
→
framework/
filters/auth
/HttpBearerAuth.php
View file @
83da0cd0
...
...
@@ -5,19 +5,31 @@
* @license http://www.yiiframework.com/license/
*/
namespace
yii\
rest
;
namespace
yii\
filters\auth
;
use
Yii
;
use
yii\base\Component
;
use
yii\web\UnauthorizedHttpException
;
/**
* HttpBearerAuth implements the authentication method based on HTTP Bearer token.
* HttpBearerAuth is an action filter that supports the authentication method based on HTTP Bearer token.
*
* You may use HttpBasicAuth by attaching it as a behavior to a controller or module, like the following:
*
* ```php
* public function behaviors()
* {
* return [
* 'bearerAuth' => [
* 'class' => \yii\filters\auth\HttpBearerAuth::className(),
* ],
* ];
* }
* ```
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
HttpBearerAuth
extends
Component
implements
AuthInterface
class
HttpBearerAuth
extends
AuthMethod
{
/**
* @var string the HTTP authentication realm
...
...
@@ -32,11 +44,10 @@ class HttpBearerAuth extends Component implements AuthInterface
$authHeader
=
$request
->
getHeaders
()
->
get
(
'Authorization'
);
if
(
$authHeader
!==
null
&&
preg_match
(
"/^Bearer
\\
s+(.*?)$/"
,
$authHeader
,
$matches
))
{
$identity
=
$user
->
loginByAccessToken
(
$matches
[
1
]);
if
(
$identity
!
==
null
)
{
return
$identity
;
if
(
$identity
=
==
null
)
{
$this
->
handleFailure
(
$response
)
;
}
$this
->
handleFailure
(
$response
);
return
$identity
;
}
return
null
;
...
...
framework/
rest
/QueryParamAuth.php
→
framework/
filters/auth
/QueryParamAuth.php
View file @
83da0cd0
...
...
@@ -5,19 +5,18 @@
* @license http://www.yiiframework.com/license/
*/
namespace
yii\
rest
;
namespace
yii\
filters\auth
;
use
Yii
;
use
yii\base\Component
;
use
yii\web\UnauthorizedHttpException
;
/**
* QueryParamAuth i
mplements the authentication method
based on the access token passed through a query parameter.
* QueryParamAuth i
s an action filter that supports the authentication
based on the access token passed through a query parameter.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
QueryParamAuth
extends
Component
implements
AuthInterface
class
QueryParamAuth
extends
AuthMethod
{
/**
* @var string the parameter name for passing the access token
...
...
framework/rest/Controller.php
View file @
83da0cd0
...
...
@@ -8,10 +8,9 @@
namespace
yii\rest
;
use
Yii
;
use
yii\
base\InvalidConfigException
;
use
yii\
filters\auth\CompositeAuth
;
use
yii\filters\RateLimiter
;
use
yii\web\Response
;
use
yii\web\UnauthorizedHttpException
;
use
yii\web\UnsupportedMediaTypeHttpException
;
use
yii\filters\VerbFilter
;
use
yii\web\ForbiddenHttpException
;
...
...
@@ -23,8 +22,9 @@ use yii\web\ForbiddenHttpException;
*
* 1. Resolving response format and API version number (see [[supportedFormats]], [[supportedVersions]] and [[version]]);
* 2. Validating request method (see [[verbs()]]).
* 3. Authenticating user (see [[authenticate()]]);
* 4. Formatting response data (see [[serializeData()]]).
* 3. Authenticating user (see [[\yii\filters\auth\AuthInterface]]);
* 4. Rate limiting (see [[\yii\filters\RateLimiter]]);
* 5. Formatting response data (see [[serializeData()]]).
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
@@ -44,12 +44,6 @@ class Controller extends \yii\web\Controller
*/
public
$enableCsrfValidation
=
false
;
/**
* @var array the supported authentication methods. This property should take a list of supported
* authentication methods, each represented by an authentication class or configuration.
* If this is not set or empty, it means authentication is disabled.
*/
public
$authMethods
;
/**
* @var string the chosen API version number, or null if [[supportedVersions]] is empty.
* @see supportedVersions
*/
...
...
@@ -80,6 +74,9 @@ class Controller extends \yii\web\Controller
'class'
=>
VerbFilter
::
className
(),
'actions'
=>
$this
->
verbs
(),
],
'auth'
=>
[
'class'
=>
CompositeAuth
::
className
(),
],
'rateLimiter'
=>
[
'class'
=>
RateLimiter
::
className
(),
],
...
...
@@ -98,15 +95,6 @@ class Controller extends \yii\web\Controller
/**
* @inheritdoc
*/
public
function
beforeAction
(
$action
)
{
$this
->
authenticate
(
$action
);
return
parent
::
beforeAction
(
$action
);
}
/**
* @inheritdoc
*/
public
function
afterAction
(
$action
,
$result
)
{
$result
=
parent
::
afterAction
(
$action
,
$result
);
...
...
@@ -157,36 +145,6 @@ class Controller extends \yii\web\Controller
}
/**
* Authenticates the user.
* This method implements the user authentication based on an access token sent through the `Authorization` HTTP header.
* @param \yii\base\Action $action the action to be executed
* @throws UnauthorizedHttpException if the user is not authenticated successfully
* @throws InvalidConfigException if an auth method declared in [[authMethods]] is invalid.
*/
protected
function
authenticate
(
$action
)
{
if
(
empty
(
$this
->
authMethods
))
{
return
;
}
$user
=
Yii
::
$app
->
getUser
();
$request
=
Yii
::
$app
->
getRequest
();
$response
=
Yii
::
$app
->
getResponse
();
foreach
(
$this
->
authMethods
as
$i
=>
$auth
)
{
$this
->
authMethods
[
$i
]
=
$auth
=
Yii
::
createObject
(
$auth
);
if
(
!
$auth
instanceof
AuthInterface
)
{
throw
new
InvalidConfigException
(
get_class
(
$auth
)
.
' must implement yii\rest\AuthInterface'
);
}
elseif
(
$auth
->
authenticate
(
$user
,
$request
,
$response
)
!==
null
)
{
return
;
}
}
/** @var AuthInterface $auth */
$auth
=
reset
(
$this
->
authMethods
);
$auth
->
handleFailure
(
$response
);
}
/**
* Serializes the specified data.
* The default implementation will create a serializer based on the configuration given by [[serializer]].
* It then uses the serializer to serialize the given data.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment