使用 Satellizer 和 Laravel 的 AngularJS 身份验证服务

Posted

技术标签:

【中文标题】使用 Satellizer 和 Laravel 的 AngularJS 身份验证服务【英文标题】:AngularJS authentication service using Satellizer and Laravel 【发布时间】:2016-10-10 03:33:04 【问题描述】:

我正在试验 Angular,试图设置一个由 laravel 后端 (REST API) 提供支持的 Angular 前端。对于身份验证,我想使用 json Web 令牌。对于 Angular,我使用的是 Satellizer (https://github.com/sahat/satellizer) 和 Laravel JWT (https://github.com/tymondesigns/jwt-auth)。

目前,我已经可以使用存储在 Laravel 中的正确凭据使用 AngularJS 登录。用户信息和令牌存储在 localStorage 中。

我想实现某种 Angular 服务,它可以检查用户是否经过身份验证,以保护来自 ui-router 的状态。我已经尝试了一些 tuts,但我无法让它工作。有人可以指出我正确的方向吗?会很棒!

登录控制器(角度)

.controller('loginCtrl', [
    '$scope',
    '$rootScope',
    'utils',
    '$auth',
    '$location',
    'SweetAlert',
    function ($scope,$rootScope,utils, $auth, $location, SweetAlert) 


        $scope.login = function() 

            var credentials = 
                email:      $scope.email,
                password:   $scope.password
            ;

            $auth.login(credentials)
                .then(function (response) 
                    var user = JSON.stringify(response.data.user);
                    localStorage.setItem('currentUser', user);
                    $location.path('/restricted.dashboard');
                )
                .catch(function (response) 
                    SweetAlert.swal("Inloggen mislukt.", "Controleer je email adres en wachtwood en probeer opnieuw.", "warning");
                    console.log("LOGIN NOT OK" + response);
                );
        ;

app.states.js(ui-router、Angular)

.config([
    '$stateProvider',
    '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) 

        // Use $urlRouterProvider to configure any redirects (when) and invalid urls (otherwise).
        $urlRouterProvider
            .when('/dashboard', '/')
            .otherwise('/');

        $stateProvider
            .state("error.404", 
                url: "/404",
                templateUrl: 'app/componentsOld/pages/error_404View.html'
            )
            .state("error.500", 
                url: "/500",
                templateUrl: 'app/componentsOld/pages/error_500View.html'
            )

            // -- LOGIN PAGE --
            .state("login", 
                url: "/login",
                templateUrl: 'app/components/auth/loginView.html',
                controller: 'loginCtrl',
                resolve: 

                    deps: ['$ocLazyLoad', function ($ocLazyLoad) 
                        return $ocLazyLoad.load([
                            'lazy_uikit',
                            'lazy_iCheck',
                            'app/components/auth/loginController.js',
                            'sweetAlert'
                        ]);
                    ]
                
            )


            // -- RESTRICTED --
            .state("restricted", 

                abstract: true,
                url: "",
                views: 
                    'main_header': 
                        templateUrl: 'app/shared/header/headerView.html',
                        controller: 'main_headerCtrl'
                    ,
                    'main_sidebar': 
                        templateUrl: 'app/shared/main_sidebar/main_sidebarView.html',
                        controller: 'main_sidebarCtrl'
                    ,
                    '': 
                        templateUrl: 'app/views/restricted.html'
                    
                ,
                resolve: 

                    deps: ['$ocLazyLoad', function ($ocLazyLoad) 
                        return $ocLazyLoad.load([
                            'lazy_uikit',
                            'lazy_selectizeJS',
                            'lazy_switchery',
                            'lazy_prismJS',
                            'lazy_autosize',
                            'lazy_iCheck',
                            'lazy_themes',
                            'lazy_style_switcher',
                            'sweetAlert'
                        ]);
                    ]
                
            )

app.js (Angular)

....
// Satellizer configuration that specifies which API
// route the JWT should be retrieved from
$authProvider.loginUrl = 'zz/zz/laravel/public/api/authenticate';

// Redirect to the auth state if any other states
// are requested other than users
$urlRouterProvider.otherwise('/auth');
....

Laravel 认证控制器(Laravel 5.2)

public function authenticate(Request $request)

    $credentials = $request->only('email', 'password');

    try 
        // verify the credentials and create a token for the user
        if (!$token = JWTAuth::attempt($credentials)) 
            return response()->json(['error' => 'invalid_credentials'], 401);
        
     catch (JWTException $e) 
        // something went wrong
        return response()->json(['error' => 'could_not_create_token'], 500);
    
    $user = Auth::user();
    //$user->company;
    //$street = $user->company->street;
    // if no errors are encountered we can return a JWT

    return response()->json([
        "token" => $token,
        "user" => $user
    ]);


我想要完成的是为 Angular 创建一个 laravel 中间件,以便我们可以检查用户是否已通过身份验证,并且将来他或她具有正确的用户角色来加载 Angular 状态。

感谢您花时间解决我的问题。我很期待看到你会如何处理这个:)

【问题讨论】:

【参考方案1】:

我不久前在某处找到了这个解决方案,它符合我的需求(还不能提供原始答案,归功于原始答案)。事件虽然我使用 $routeProvider,但我认为您可以使用 $stateProvider 应用类似的逻辑

.config(function ($routeProvider) 
    $routeProvider
    .when('/awesomeRoute', 
            templateUrl: 'views/view.tpl.html',
            controller: 'someAwesomeCtrl',
            controllerAs: 'someCtrl',
            resolve : 
                  //This function is injected with the AuthService where you'll put your authentication logic
                  'auth' : function(AuthService)
                      return AuthService.authenticate();
                  


                 
              )
        )

身份验证服务:

 .factory('AuthService', function($q, Service, $window, $location)
          return 
              authenticate : function()
                  //Authentication logic here, some service to check 
against backend if token you provided is valid and/or you are authorized to enter those sections of application, 
or in your case with satellizer you can use `$auth.isAuthenticated()` method.

                    Service.isTokenValid(_yourToken).then( (res) => 
                      if(res.data === true)
                        return true;
                       else 
                        return $q.reject('Not Authenticated');
                      
                    , (err) => 
                      $location.path('/');
                        return $q.reject('Not Authenticated');
                    )
                   else 
                    return $q.reject('Not Authenticated');
                  
              
          ;
      )

最后是“路由错误捕获器”,当出现问题时,返回 home 或 /auth 路由

.run(function($rootScope, $location)
    //If the route change failed due to authentication error, redirect them out
    $rootScope.$on('$routeChangeError', function(event, current, previous, rejection)
        if(rejection === 'Not Authenticated')
            $location.path('/');
        
    );
  )

【讨论】:

以上是关于使用 Satellizer 和 Laravel 的 AngularJS 身份验证服务的主要内容,如果未能解决你的问题,请参考以下文章

使用 JWT 进行 laravel 身份验证的 Satellizer 警告“期待一个名为 token 的令牌”

JWT Auth 和 Satellizer - 增加移动应用程序的到期令牌时间

JWT 授权 laravel / angularjs 问题

JWT 令牌失效的未知原因

Laravel 未检测到标头和 JWT 包中发送的身份验证令牌

页面刷新时,Satellizer 登录 JWT 令牌消失了