AngularJS: How to hide the template content until user is authenticated?

半世苍凉 提交于 2019-12-22 18:28:14

问题


My app has 2 pages: main.html and login.html. When not authenticated users go to /main they should be redirected to /login.

The problem is that main.html is rendered first, and after a second or so, when user authentication fails, login.html is rendered.

How could I prevent from main.html to be rendered until authentication succeeds?

Here is the relevant code (CoffeeScript):

angular.module('myApp', [...])
.config(['$routeProvider', ($routeProvider) ->
  $routeProvider.when '/login',
    templateUrl: 'html/login.html'
    controller: LoginController

  $routeProvider.otherwise
    templateUrl: 'html/main.html'
    controller: MainController
])
.run(['$rootScope', '$location', 'appService', ($rootScope, $location, app) ->
  $rootScope.$on '$locationChangeStart', (event, newValue, oldValue) ->
    return if newValue == '/login'

    $.when(app.authenticate()).fail ->
      $location.path '/login'
      $rootScope.$apply()
])

angular.module('myApp.services').factory 'appService' , () ->
  rootRef = new Firebase('https://myapp.firebaseio.com')

  user: null
  authenticate: ->
    deferred = $.Deferred()

    authClient = new FirebaseAuthClient rootRef, (error, user) =>
      if error
        # An error occurred while attempting login
        @user = null
        deferred.reject()
      else if user
        # User authenticated with Firebase
        @user = user
        deferred.resolve()
      else
        # User is logged out
        @user = null
        deferred.reject()

    deferred.promise()

回答1:


Well, I don't serve the template (in your case main.html) until the user is authenticated. I have a customized function on server for serving templates, which checks if the user is authenticated. If in the function I find out the user is not logged in, it returns response with 401 status code. In angular code I then hold the request until the authentication and then ask for the template again.

I was inspired to do this by this post: http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application




回答2:


My solution to the same requirement was to define the following watch:

$rootScope.$watch(
    function() {
        return $location.path();
    },
    function(newValue, oldValue) {  
        if (newValue != '/login' && user is not logged in) {
            $location.path('/login');  
        }
    },
    true);

in a controller associated with the body element of the index page (i. e. the page containing the ng-view directive).




回答3:


One option is to hide the normal DOM and show an "Authenticating..." message, maybe with a spinner, to give the user some idea of why he/she is sitting there waiting for something to happen. In main.html, include something like:

<spinner ng-hide="appService.wrapper.user"></spinner>
<!-- everything else ng-show="appService.wrapper.user" -->

where <spinner></spinner> is an Angular directive that is replaced by your custom "Authenticating..." message, and user is a variable your appService makes available to MainController. Note that you may need to wrap user in an object within appService, like so:

.service('appService', function() {

  var wrapper = {
    user: null
  };

  function authenticate() {
    // start the authentication and return the promise,
    // but modify wrapper.user instead of user
  }

  return wrapper;

});

You'll also need to store either appService or appService.wrapper in the $scope variable of your MainController.



来源:https://stackoverflow.com/questions/15024253/angularjs-how-to-hide-the-template-content-until-user-is-authenticated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!