【问题标题】:Token based authentication and authorization with angular and yii2 using oAuth2 protocol(HttpBearerAuth)使用 oAuth2 协议(HttpBearerAuth)使用 Angular 和 yii2 进行基于令牌的身份验证和授权
【发布时间】:2015-10-22 00:19:18
【问题描述】:

我正在尝试使用基于令牌的身份验证和授权来执行登录,但由于在我的主配置文件中设置了 ApiController 操作仪表板的授权,因此我卡住了:

'enableSession' => false,

在 ApiController 中,我有:

public function actionDashboard()
    {
        $response = [
            'username' => Yii::$app->user->identity->username,
            'access_token' => Yii::$app->user->identity->getAuthKey(),
        ];
        return $response;
    }

我无法正确使用令牌执行授权过程。这是我的完整代码。

main-local.php:

<?php
use \yii\web\Request;

$baseUrl = str_replace('/frontend/web', '', (new Request)->getBaseUrl());

$config = [
    'language' => 'en-US',
    'name'=>'Lead Battery Recycling',
     'components' => [
         'user' => [
             'identityClass' => 'common\models\User',
    'enableSession' => false,
    'loginUrl' => null,

            'enableAutoLogin' => false,
            'identityCookie' => [
                'name' => '_frontendUser', // unique for backend
                'path'=>'/gravita_lbp/frontend/web'  // correct path for the backend app.
            ]
        ],
         'session' => [
            'name' => 'PHPFRONTSESSID',
            'savePath' => __DIR__ . '/../tmp',
        ],
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => '7ZO7uJfychV7ozQOPnfQGS6zdXLz9Lx0',
            'baseUrl' => $baseUrl,
            'parsers' => [
                 'application/json' => 'yii\web\JsonParser',
            ]
        ],
        'urlManager' => [
            'class' => 'yii\web\UrlManager',
            'baseUrl' => $baseUrl,
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            //'enableStrictParsing' => true,
            'rules' => [
                ['class' => 'yii\rest\UrlRule', 'controller' => 'api'],
            ],
        ],
           'urlManagerBackEnd' => [
            'class' => 'yii\web\urlManager',
            'baseUrl' => '/gravita_lbp/backend/web/',
            'enablePrettyUrl' => true,
            'showScriptName' => false,
        ],
    ],
    'as access' => [
        'class' => 'mdm\admin\components\AccessControl',
        'allowActions' => [
           'site/*',
            'api/login',
            'api/dashboard' // add or remove allowed actions to this list
        ]
    ],


];
if (!YII_ENV_TEST) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = 'yii\debug\Module';

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = 'yii\gii\Module';
}

return $config;

ApiController.php:

<?php
namespace frontend\controllers;
use Yii;
use common\models\LoginForm;
use frontend\models\ContactForm;
use yii\filters\ContentNegotiator;
use yii\web\Response;
use yii\filters\AccessControl;
use yii\rest\Controller;
use yii\filters\auth\HttpBearerAuth;
/**
 * Site controller
 */
class ApiController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => HttpBearerAuth::className(),
            'only' => ['dashboard'],
        ];
        $behaviors['contentNegotiator'] = [
            'class' => ContentNegotiator::className(),
            'formats' => [
                'application/json' => Response::FORMAT_JSON,
            ],
        ];
        $behaviors['access'] = [
            'class' => AccessControl::className(),
            'only' => ['dashboard'],
            'rules' => [
                [
                    'actions' => ['dashboard'],
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ];
        return $behaviors;
    }

    public function actionLogin()
    {    

        $model = new LoginForm();
        if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->login()) {

            return ['access_token' => Yii::$app->user->identity->getAuthKey()];
        } else {
            $model->validate();
            return $model;
        }

    }
    public function actionDashboard()
    {

        $response = [
            'username' => Yii::$app->user->identity->username,
            'access_token' => Yii::$app->user->identity->getAuthKey(),
        ];
        return $response;
    }
    public function actionContact()
    {
        $model = new ContactForm();
        if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->validate()) {
            if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
                $response = [
                    'flash' => [
                        'class' => 'success',
                        'message' => 'Thank you for contacting us. We will respond to you as soon as possible.',
                    ]
                ];
            } else {
                $response = [
                    'flash' => [
                        'class' => 'error',
                        'message' => 'There was an error sending email.',
                    ]
                ];
            }
            return $response;
        } else {
            $model->validate();
            return $model;
        }
    }
}

controller.js:

'use strict';

var controllers = angular.module('controllers', []);

controllers.controller('MainController', ['$scope', '$location', '$window',
    function ($scope, $location, $window) {
        $scope.loggedIn = function() {
            return Boolean($window.sessionStorage.access_token);
        };

        $scope.logout = function () {
            delete $window.sessionStorage.access_token;
            $location.path('/login').replace();
        };
    }
]);

controllers.controller('ContactController', ['$scope', '$http', '$window',
    function($scope, $http, $window) {
        $scope.captchaUrl = 'site/captcha';
        $scope.contact = function () {
            $scope.submitted = true;
            $scope.error = {};
            $http.post('api/contact', $scope.contactModel).success(
                function (data) {
                    $scope.contactModel = {};
                    $scope.flash = data.flash;
                    $window.scrollTo(0,0);
                    $scope.submitted = false;
                    $scope.captchaUrl = 'site/captcha' + '?' + new Date().getTime();
            }).error(
                function (data) {
                    angular.forEach(data, function (error) {
                        $scope.error[error.field] = error.message;
                    });
                }
            );
        };

        $scope.refreshCaptcha = function() {
            $http.get('site/captcha?refresh=1').success(function(data) {
                $scope.captchaUrl = data.url;
            });
        };
    }]);

controllers.controller('DashboardController', ['$scope', '$http',
    function ($scope, $http) {
        $http.get('/lbp/api/dashboard').success(function (data) {
           $scope.dashboard = data;
        })
    }
]);

controllers.controller('LoginController', ['$scope', '$http', '$window', '$location',
    function($scope, $http, $window, $location) {
        $scope.login = function () {
            $scope.submitted = true;
            $scope.error = {};
            $http.post('/lbp/api/login', $scope.userModel).success(
                function (data) {
                    $window.sessionStorage.access_token = data.access_token;
                    $location.path('/dashboard').replace();
            }).error(
                function (data) {
                    angular.forEach(data, function (error) {
                        $scope.error[error.field] = error.message;
                    });
                }
            );
        };
    }
]);

请为此建议我一个解决方案,我只想通过使用 rest API 来做到这一点。

【问题讨论】:

    标签: angularjs api authorization yii2 token


    【解决方案1】:

    我迟到了,但可能对未来的读者有帮助。

    您需要在每个请求中发送您的 access_token。假设,创建一个名为 auth.js 的简单工厂

    app.factory('authInterceptor', function($q, $window, $rootScope) {
      return {
        request: function(config) {
          if ($window.sessionStorage.access_token) {
            //HttpBearerAuth
            config.headers.Authorization = 'Bearer ' +     $window.sessionStorage.access_token;
          }
          return config;
        },
      }
    });
    

    并添加

    $httpProvider.interceptors.push('authInterceptor');
    

    在你的 angular.module 里面,它可以帮助你添加

    Authorization:Bearer your_access_token
    

    在请求标头中。您的 Yii 控制器行为使用它来验证您的用户。

    【讨论】:

      【解决方案2】:

      由于 RESTful API 是无状态的, 所以你应该保持会话设置为假。 然后,您无需将两个单独的问题混为一谈;

      • 开发者身份验证
      • 最终用户身份验证

      通常,您应首先对开发人员进行身份验证 在允许他们使用 API 之前 基本凭证或不记名令牌。 之后,您应将资源公开为端点 开发人员可以查询。那是你可以考虑打破 仪表板下到可以单独查询的组件。

      【讨论】:

        猜你喜欢
        • 2021-12-06
        • 2016-10-14
        • 2016-04-24
        • 2015-05-12
        • 2016-08-24
        • 2018-01-01
        • 1970-01-01
        • 2020-04-13
        • 2017-12-10
        相关资源
        最近更新 更多