Подтвердить что ты не робот

Аутентификация Angular js-модуля для Apigility

Я создал API с использованием Apigility. Я пытаюсь установить систему аутентификации для внешнего приложения, которое я сейчас создаю с помощью API.

Но все модули проверки подлинности angular, которые я использовал для этой системы аутентификации, не соответствуют реализации Apigility oAuth 2:

  • https://github.com/lynndylanhurley/ng-token-auth Проблема с этим модулем заключается в том, что он не позволяет CORS. Однако он позволяет отправлять запрос CORS с использованием прокси-сервера на сервере, где находится angular код, который я написал на PHP с помощью Guzzle. Но с proxy ng-token-auth отправьте запрос дважды успешно, даже если все данные аутентификации являются ложными.

  • https://github.com/sahat/satellizer Этот модуль нуждается в реализации JWT, но в разделе "Проверка подлинности Apigility" я не видел на нем никакой документации.

Мне нужна помощь для завершения моего проекта.

4b9b3361

Ответ 1

Я попытаюсь дать полный метод, как я сделал ng-token-auth работать с ZF2. В первую очередь, ng-token-auth отлично работает с модулем ruby. Поэтому, чтобы заставить его работать с ZF2:

Устранить проблему CORS с этими строками кода:

//HttpProvider
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common['Access-Control-Request-Method'] = "POST, GET, PUT, DELETE";
$httpProvider.defaults.headers.common['Origin'] = "http://xxxxxxxxxxxxxxx";
$httpProvider.defaults.headers.common['Accept'] = "application/json";
$httpProvider.defaults.headers.common['Content-Type'] = "application/json; text/html";
delete $httpProvider.defaults.headers.common['X-Requested-With'];

Устранить проблему CORS на ZF2, используя ZFCORS, как указано в @josilber и @sven-lauterbach answer

Отклик формата, отправленный ZF2, чтобы заставить его работать с ng-token-auth, используя эти строки кодов

$http.defaults.transformResponse = function(value, headerGetters){
    var response_header = headerGetters(),
    response_data   = JsonHelper.IsJsonString(value) ? JSON.parse(value) : value;
    if(response_data){
        if(response_data.access_token)
            response_header['access_token']  = response_data.access_token;
        if(response_data.expires_in){
            var now = new Date().getTime();
            response_header['expires_in']    = now + ( parseInt(response_data.expires_in, 10) * 1000 );
        } 
        if(response_data.token_type)
            response_header['token_type']    = response_data.token_type;
        if(response_data.refresh_token)
            response_header['refresh_token'] = response_data.refresh_token;
        if(response_data.scope)
            response_header['scope']         = response_data.scope;
        return response_data;
    }
};

Может быть, это не лучший способ преобразования ответа в AngularJS, но он решает проблему форматирования ответа OAuth2, который работает с ng-token-auth

Наконец, чтобы отправить запрос на сервер с использованием токена аутентификации и обновить токен автоматически, необходимо было изменить некоторое поведение ng-token-auth. Я использовал украшение шаблона на AngularJS, чтобы решить эту проблему с этими фрагментами кода:

В app.js

//Change behavior of oauth2 module 
$provide.decorator("$auth", function($delegate, ApiAuthService){
    return ApiAuthService($delegate);
}); 

Где ApiAuthService - это factory, определенный этим фрагментом кода:

AuthProviderService.factory('ApiAuthService', ['MeService', function( MeService ){
    return function($delegate){
        return {
            initialize: function(){ return $delegate.initialize(); },
            apiUrl: function(configName){ },
            retrieveData: function(key){ return $delegate.retrieveData(key); },
            getConfig: function(name){ return $delegate.getConfig(name); },
            getExpiry: function(){  return $delegate.getExpiry(); },
            setAuthHeaders: function(h){ return $delegate.setAuthHeaders(h); },
            /*persistData: function(key, val, configName){ return $delegate.persistData(key, val, configName); },
            retrieveData: function(key){ return $delegate.retrieveData(key); },*/
            rejectDfd: function(reason){ $delegate.rejectDfd(reason); },
            invalidateTokens: function(){ return $delegate.invalidateTokens(); },
            submitLogin: function(params, opts){ return $delegate.submitLogin(params, opts); },
            validateUser: function(opts){  
                result = $delegate.validateUser(opts);
                return result;
            },
            deleteData: function(key){  
                return $delegate.deleteData(key);
            }
        };
    };
}]).config(['$httpProvider', function($httpProvider) {

    $httpProvider.interceptors.push([
         '$injector', function($injector) {
           return {
             request: function(req) {
               $injector.invoke([
                 '$http', '$auth', function($http, $auth) {
                   var key, 
                       _ref, 
                       _results = [];
                   if (req.url.match($auth.apiUrl())) {
                     _ref = $auth.retrieveData('auth_headers');
                     //Inject value into body of request 
                     for (key in _ref) {
                         //Set Authorization request header.
                         if(key.match('access_token')){
                             if(req.headers){
                                 req.headers['Authorization'] = 'Bearer ' + _ref[key]; 
                             }else{
                                 req.headers = {'Authorization': 'Bearer ' + _ref[key]};
                             }
                         }
                         if(req.headers[key]){
                             delete req.headers[key];
                         }
                     }
                     return _results;
                   }
                 }
               ]);
               return req;
             }
           };
         }
       ]);
}]);

Наконец, моя конфигурация ng-token-auth была:

//OAuth2 Module configs
$authProvider.configure([ {
    "default": {
        apiUrl:                  API_URL,
        tokenValidationPath:     '/me',
        signOutUrl:              '/oauth',
        emailRegistrationPath:   '/oauth',
        accountUpdatePath:       '/oauth',
        accountDeletePath:       '/oauth',
        confirmationSuccessUrl:  window.location.href,
        passwordResetPath:       '/oauth',
        passwordUpdatePath:      '/oauth',
        passwordResetSuccessUrl: window.location.href,
        emailSignInPath:         '/oauth',
        forceHardRedirect: true,
        storage:                 'localStorage',
        proxyIf:                 function() { return false; },
        proxyUrl:                'proxy',
        authProviderPaths: {
            github:   '/auth/github',
            facebook: '/auth/facebook',
            google:   '/auth/google'
        },
        tokenFormat: {
            "access_token" : "{{ token }}",
            "token_type"   : "Bearer",
            "refresh_token": "{{ clientId }}",
            "expires_in"   : "{{ expiry }}",
            "scope"        : "{{ uid }}"
        },
        parseExpiry: function(headers) {
            var expires_in = parseInt(headers['expires_in'], 10) || null;
                return expires_in;
            },
            handleLoginResponse: function(response) {
                //Patch for persistant data as library retreive auth data from header.
                return response;
            },
            handleAccountResponse: function(response) {
                return response;
            },
            handleTokenValidationResponse: function(response) {
                return response;
            }
        }
} ]);

@JerinKAlexander Я надеюсь, что эти шаги помогут вам найти способ решить свой вопрос лучше, чем то, что я сделал.

Ответ 2

Фактически вы можете satellizer работать с Apigility с помощью довольно простого, но аккуратного обходного пути. Посмотрите здесь:

http://adam.lundrigan.ca/2014/11/06/using-oauth2-jwt-with-apigility/

и здесь:

https://github.com/adamlundrigan/LdcOAuth2CryptoToken/blob/master/src/Factory/CryptoTokenServerFactory.php

Apigility определяет сервисные заводы для всех внутренних служб. Основная идея здесь заключается в простом делегировании диспетчера служб factory, который вводит необходимую конфигурацию.

<?php  
namespace LdcOAuth2CryptoToken\Factory;

use Zend\ServiceManager\DelegatorFactoryInterface;  
use Zend\ServiceManager\ServiceLocatorInterface;
class CryptoTokenServerFactory implements DelegatorFactoryInterface  
{
    public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
    {
        $server = call_user_func($callback);

        // do your thing to $server here

        return $server;
    }
}

Все спасибо Adam Lundrigan:)

Ответ 3

Вы хотите использовать Apigility в качестве backend. У вас есть приложение HTML, которое работает в другом домене, и это приложение HTML должно вызывать сервер Apigility с аутентификацией OAuth? Если это то, что вы пытаетесь выполнить, вам нужно настроить Apigility для поддержки вызовов CORS, посмотрите https://apigility.org/documentation/recipes/allowing-request-from-other-domains

Они используют модуль "ZfrCors":

Они используют следующий пример:

return array(
'zfr_cors' => array(
     /**
      * Set the list of allowed origins domain with protocol.
      */
     'allowed_origins' => array('http://www.sexywidgets.com'),

     /**
      * Set the list of HTTP verbs.
      */
     'allowed_methods' => array('GET', 'OPTIONS'),

     /**
      * Set the list of headers. This is returned in the preflight request to indicate
      * which HTTP headers can be used when making the actual request
      */
     'allowed_headers' => array('Authorization', 'Content-Type'),

     /**
      * Set the max age of the preflight request in seconds. A non-zero max age means
      * that the preflight will be cached during this amount of time
      */
     // 'max_age' => 120,

     /**
      * Set the list of exposed headers. This is a whitelist that authorize the browser
      * to access to some headers using the getResponseHeader() JavaScript method. Please
      * note that this feature is buggy and some browsers do not implement it correctly
      */
     // 'exposed_headers' => array(),

     /**
      * Standard CORS requests do not send or set any cookies by default. For this to work,
      * the client must set the XMLHttpRequest "withCredentials" property to "true". For
      * this to work, you must set this option to true so that the server can serve
      * the proper response header.
      */
     // 'allowed_credentials' => false,
),
);

Все, что вам нужно - это установить параметр allow_origins в домен вашего HTML-приложения.

Для части OAuth вы можете получить дополнительную информацию здесь: https://apigility.org/documentation/auth/authentication-oauth2

Вам следует более внимательно ознакомиться с разделом "Приложения на основе браузера", потому что вы используете приложение HTML для доступа к бэкэнду. С информацией, представленной в этом сообщении, вы можете использовать https://github.com/sahat/satellizer

Если вам нужна дополнительная информация, дайте мне знать.