AngularJS ui- राउटर लॉगिन प्रमाणीकरण


376

मैं AngularJS के लिए नया हूं, और मैं थोड़ा भ्रमित हूं कि मैं निम्नलिखित परिदृश्य में कोणीय- "ui- राउटर" का उपयोग कैसे कर सकता हूं:

मैं एक वेब एप्लिकेशन बना रहा हूं जिसमें दो सेक्शन हैं। पहला खंड अपने लॉगिन और साइनअप दृश्यों के साथ होमपेज है, और दूसरा खंड डैशबोर्ड (सफल लॉगिन के बाद) है।

मैंने index.htmlअपने कोणीय ऐप और ui-routerहैंडल /loginऔर /signupविचारों को कॉन्फ़िगर करने के लिए होम सेक्शन के लिए बनाया है , और इस dashboard.htmlऐप के साथ डैशबोर्ड सेक्शन के लिए एक और फाइल है औरui-router कॉन्फिगरेशन के कई सब व्यूज को हैंडल करने के लिए।

अब मैंने डैशबोर्ड अनुभाग समाप्त कर दिया है और यह नहीं जानता कि दोनों वर्गों को उनके विभिन्न कोणीय ऐप के साथ कैसे जोड़ा जाए। मैं डैशबोर्ड ऐप पर रीडायरेक्ट करने के लिए होम ऐप को कैसे बता सकता हूं?


1
क्या आप हमारे साथ कुछ कोड साझा कर सकते हैं?
चाचो

6
@ मुझे लगता है कि यह कोड के बारे में नहीं है, वास्तव में मुझे नहीं पता कि मुझे किस कोड को साझा करना चाहिए।
अहमद हशेम

हां, कृपया कोड साझा करें, बहुत ही सामान्य प्रश्न ...
Alireza

जवाबों:


607

मैं एक अच्छा प्रदर्शन करने के साथ-साथ एक उपयोगी मॉड्यूल में इन सेवाओं में से कुछ को साफ करने की प्रक्रिया में हूं, लेकिन यहां मैं आपके साथ आया हूं। कुछ कैविटीज़ के आसपास काम करने के लिए यह एक जटिल प्रक्रिया है, इसलिए इसमें लटके रहें। आपको इसे कई टुकड़ों में तोड़ना होगा।

इस डुबकी पर एक नज़र डालें

सबसे पहले, आपको उपयोगकर्ता की पहचान को संग्रहीत करने के लिए एक सेवा की आवश्यकता है। मैं इसे कॉल करता हूं principal। यह देखने के लिए जाँच की जा सकती है कि उपयोगकर्ता लॉग इन है, और अनुरोध पर, यह उपयोगकर्ता की पहचान के बारे में आवश्यक जानकारी का प्रतिनिधित्व करने वाली वस्तु को हल कर सकता है। यह आप की जरूरत है जो कुछ भी हो सकता है, लेकिन अनिवार्य एक प्रदर्शन नाम होगा, एक उपयोगकर्ता नाम, संभवतः एक ईमेल, और भूमिकाएं जो एक उपयोगकर्ता की है (यदि यह आपके ऐप पर लागू होती है)। प्रिंसिपल के पास रोल चेक करने के तरीके भी हैं।

.factory('principal', ['$q', '$http', '$timeout',
  function($q, $http, $timeout) {
    var _identity = undefined,
      _authenticated = false;

    return {
      isIdentityResolved: function() {
        return angular.isDefined(_identity);
      },
      isAuthenticated: function() {
        return _authenticated;
      },
      isInRole: function(role) {
        if (!_authenticated || !_identity.roles) return false;

        return _identity.roles.indexOf(role) != -1;
      },
      isInAnyRole: function(roles) {
        if (!_authenticated || !_identity.roles) return false;

        for (var i = 0; i < roles.length; i++) {
          if (this.isInRole(roles[i])) return true;
        }

        return false;
      },
      authenticate: function(identity) {
        _identity = identity;
        _authenticated = identity != null;
      },
      identity: function(force) {
        var deferred = $q.defer();

        if (force === true) _identity = undefined;

        // check and see if we have retrieved the 
        // identity data from the server. if we have, 
        // reuse it by immediately resolving
        if (angular.isDefined(_identity)) {
          deferred.resolve(_identity);

          return deferred.promise;
        }

        // otherwise, retrieve the identity data from the
        // server, update the identity object, and then 
        // resolve.
        //           $http.get('/svc/account/identity', 
        //                     { ignoreErrors: true })
        //                .success(function(data) {
        //                    _identity = data;
        //                    _authenticated = true;
        //                    deferred.resolve(_identity);
        //                })
        //                .error(function () {
        //                    _identity = null;
        //                    _authenticated = false;
        //                    deferred.resolve(_identity);
        //                });

        // for the sake of the demo, fake the lookup
        // by using a timeout to create a valid
        // fake identity. in reality,  you'll want 
        // something more like the $http request
        // commented out above. in this example, we fake 
        // looking up to find the user is
        // not logged in
        var self = this;
        $timeout(function() {
          self.authenticate(null);
          deferred.resolve(_identity);
        }, 1000);

        return deferred.promise;
      }
    };
  }
])

दूसरा, आपको एक ऐसी सेवा की आवश्यकता है जो उपयोगकर्ता को जिस राज्य में जाना चाहता है, उसकी जांच करता है, यह सुनिश्चित करता है कि वे लॉग इन हैं (यदि आवश्यक हो, साइनइन, पासवर्ड रीसेट, आदि के लिए आवश्यक नहीं है), और फिर एक भूमिका जांच (यदि आपका ऐप है) इसकी जरूरत है)। यदि वे प्रमाणित नहीं हैं, तो उन्हें साइन-इन पृष्ठ पर भेजें। यदि उन्हें प्रमाणित किया जाता है, लेकिन एक भूमिका जांच विफल हो जाती है, तो उन्हें एक एक्सेस अस्वीकृत पृष्ठ पर भेजें। मैं इस सेवा को कॉल करता हूं authorization

.factory('authorization', ['$rootScope', '$state', 'principal',
  function($rootScope, $state, principal) {
    return {
      authorize: function() {
        return principal.identity()
          .then(function() {
            var isAuthenticated = principal.isAuthenticated();

            if ($rootScope.toState.data.roles
                && $rootScope.toState
                             .data.roles.length > 0 
                && !principal.isInAnyRole(
                   $rootScope.toState.data.roles))
            {
              if (isAuthenticated) {
                  // user is signed in but not
                  // authorized for desired state
                  $state.go('accessdenied');
              } else {
                // user is not authenticated. Stow
                // the state they wanted before you
                // send them to the sign-in state, so
                // you can return them when you're done
                $rootScope.returnToState
                    = $rootScope.toState;
                $rootScope.returnToStateParams
                    = $rootScope.toStateParams;

                // now, send them to the signin state
                // so they can log in
                $state.go('signin');
              }
            }
          });
      }
    };
  }
])

अब तुम सब है को सुन सब करने की ज़रूरत ui-routerहै $stateChangeStart। यह आपको वर्तमान स्थिति की जांच करने का मौका देता है, जिस राज्य में वे जाना चाहते हैं, और अपने प्राधिकरण की जांच डालें। यदि यह विफल रहता है, तो आप मार्ग परिवर्तन को रद्द कर सकते हैं, या किसी भिन्न मार्ग में परिवर्तन कर सकते हैं।

.run(['$rootScope', '$state', '$stateParams', 
      'authorization', 'principal',
    function($rootScope, $state, $stateParams, 
             authorization, principal)
{
      $rootScope.$on('$stateChangeStart', 
          function(event, toState, toStateParams)
      {
        // track the state the user wants to go to; 
        // authorization service needs this
        $rootScope.toState = toState;
        $rootScope.toStateParams = toStateParams;
        // if the principal is resolved, do an 
        // authorization check immediately. otherwise,
        // it'll be done when the state it resolved.
        if (principal.isIdentityResolved()) 
            authorization.authorize();
      });
    }
  ]);

किसी उपयोगकर्ता की पहचान को ट्रैक करने के बारे में मुश्किल हिस्सा यह देख रहा है कि क्या आपने पहले ही प्रमाणित कर लिया है (कहते हैं, आप पिछले सत्र के बाद पृष्ठ पर जा रहे हैं, और कुकी में एक ऑर्टिकल टोकन सहेजा है, या हो सकता है कि आपने पृष्ठ को हार्ड रिफ्रेश किया हो, या एक लिंक से एक यूआरएल पर गिरा दिया)। ui-routerकाम करने के तरीके के कारण , आपको अपनी पहचान जाँचने से पहले एक बार अपनी पहचान का समाधान करने की आवश्यकता है। आप resolveअपने राज्य कॉन्फ़िगरेशन में विकल्प का उपयोग करके ऐसा कर सकते हैं । साइट के लिए मेरे पास एक मूल राज्य है जो सभी राज्यों से विरासत में मिला है, जो प्रिंसिपल को कुछ और होने से पहले हल करने के लिए मजबूर करता है।

$stateProvider.state('site', {
  'abstract': true,
  resolve: {
    authorize: ['authorization',
      function(authorization) {
        return authorization.authorize();
      }
    ]
  },
  template: '<div ui-view />'
})

यहाँ एक और समस्या है ... resolveकेवल एक बार कॉल किया जाता है। एक बार पहचान के लिए आपका वादा पूरा होने पर, यह फिर से प्रतिनिधि प्रतिनिधि को नहीं चलाएगा। इसलिए हमें आपके दो स्थानों पर अपनी जाँच करनी है: एक बार अपने पहचान के वादे के अनुसार resolve, जो पहली बार आपके ऐप के लोड को कवर करता है, और एक बार$stateChangeStart यदि रिज़ॉल्यूशन हो चुका है, तो आप किसी भी समय राज्यों के चारों ओर नेविगेट करते हैं।

ठीक है, तो हमने अब तक क्या किया है?

  1. हम यह देखने के लिए जांचते हैं कि उपयोगकर्ता लॉग इन होने पर ऐप लोड करता है या नहीं।
  2. हम उपयोगकर्ता में लॉग इन के बारे में जानकारी ट्रैक करते हैं।
  3. हम उन्हें उन राज्यों के लिए राज्य में साइन इन करने के लिए पुनर्निर्देशित करते हैं जिनके लिए उपयोगकर्ता को लॉग इन करने की आवश्यकता होती है।
  4. यदि वे इसे एक्सेस करने के लिए प्राधिकरण नहीं रखते हैं, तो हम उन्हें एक एक्सेस अस्वीकृत राज्य में पुनर्निर्देशित करते हैं।
  5. यदि हमारे पास लॉग इन करने की आवश्यकता है, तो हमारे पास उपयोगकर्ताओं को मूल स्थिति में वापस लाने के लिए एक तंत्र है।
  6. हम एक उपयोगकर्ता को साइन आउट कर सकते हैं (आपके ग्राहक टिकट को प्रबंधित करने वाले किसी भी क्लाइंट या सर्वर कोड के साथ कॉन्सर्ट में वायर्ड होने की आवश्यकता है)।
  7. हमें हर बार अपने ब्राउज़र को पुनः लोड करने या किसी लिंक पर छोड़ने के लिए उपयोगकर्ताओं को साइन-इन पृष्ठ पर वापस भेजने की आवश्यकता नहीं है।

हम यहाँ से कहाँ जायेंगे? ठीक है, आप अपने राज्यों को उन क्षेत्रों में व्यवस्थित कर सकते हैं जिनमें साइन इन करने की आवश्यकता होती है। आप इन राज्यों के साथ (या यदि आप विरासत का उपयोग करना चाहते हैं, तो उनके dataसाथ जोड़कर) प्रमाणित / अधिकृत उपयोगकर्ताओं की आवश्यकता हो सकती है roles। यहाँ, हम एक संसाधन को Admins तक सीमित करते हैं:

.state('restricted', {
    parent: 'site',
    url: '/restricted',
    data: {
      roles: ['Admin']
    },
    views: {
      'content@': {
        templateUrl: 'restricted.html'
      }
    }
  })

अब आप राज्य-दर-राज्य को नियंत्रित कर सकते हैं कि उपयोगकर्ता किस मार्ग तक पहुंच सकते हैं। कोई और चिंता? शायद वे लॉग इन हैं या नहीं, इसके आधार पर किसी दृश्य का केवल एक हिस्सा अलग-अलग हो सकता है? कोई दिक्कत नहीं है। principal.isAuthenticated()या का भी उपयोग करेंprincipal.isInRole()उन सभी तरीकों से भी जिनके साथ आप सशर्त रूप से टेम्पलेट या तत्व प्रदर्शित कर सकते हैं, का ।

सबसे पहले, principalएक नियंत्रक या जो कुछ भी इंजेक्षन करें , और इसे दायरे में चिपका दें ताकि आप इसे आसानी से अपने दृश्य में उपयोग कर सकें:

.scope('HomeCtrl', ['$scope', 'principal', 
    function($scope, principal)
{
  $scope.principal = principal;
});

एक तत्व दिखाएं या छिपाएँ:

<div ng-show="principal.isAuthenticated()">
   I'm logged in
</div>
<div ng-hide="principal.isAuthenticated()">
  I'm not logged in
</div>

आदि, इत्यादि। वैसे भी, आपके उदाहरण ऐप में, आपके पास होम पेज के लिए एक राज्य होगा जो अनधिकृत उपयोगकर्ताओं को छोड़ देगा। उनके पास साइन-इन या साइन-अप स्थिति के लिंक हो सकते हैं, या उन रूपों को उस पेज में बनाया जा सकता है। जो भी आपको सूट करे।

डैशबोर्ड पृष्ठ उन सभी स्थितियों से भिन्न हो सकते हैं जिनमें उपयोगकर्ताओं को लॉग इन करने की आवश्यकता होती है, और कहते हैं कि Userभूमिका सदस्य बनें। हमारे द्वारा चर्चा की गई सभी प्राधिकरण सामग्री वहाँ से प्रवाहित होगी।


28
धन्यवाद, यह वास्तव में मुझे अपना कोड एक साथ लाने में मदद करता है। साइड नोट पर, यदि आपको एक अनंत राउटिंग लूप (यूआई राउटर बग) मिलता है, तो $location.pathइसके बजाय प्रयास करें $state.go
jvannistelrooy

2
यह एक शानदार जवाब है और इसने मुझे एक बहुत मदद की है। जब मैं उपयोगकर्ता = प्रिंसिपल को अपने कंट्रोलर में सेट करता हूं और कॉल करने की कोशिश करता हूं तो user.identity () कहलाता है। वर्तमान में यूजर्स के नाम पर लॉग इन करने के लिए मेरा नाम केवल वादे की वस्तु लगता है {तब: fn, पकड़: fn, आखिर :} लौटा और वास्तविक वास्तविक वस्तु नहीं। अगर मैं user.identity.then (fn (user)) का उपयोग करता हूं, तो मुझे उपयोगकर्ता ऑब्जेक्ट मिल सकता है लेकिन यह देखने के लिए बहुत सारे कोड जैसा लगता है कि क्या मुझे कुछ याद आ रहा है?
मार्क

4
@ Ir1sh मैं नियंत्रक में सबसे पहले पहचान को हल करूंगा और इसे $scope.userआपके thenफ़ंक्शन में असाइन करूंगा । आप अभी भी userअपने विचारों में संदर्भ ले सकते हैं; जब इसे हल किया जाता है, तो दृश्य अपडेट किया जाएगा।
moribvndvs

2
@HackedByChinese मुझे लगता है कि आपका डेमो अब काम नहीं कर रहा है।
ब्‍लॉसी

7
@jvannistelrooy मुझे जाने () के साथ समस्या थी, लेकिन इस तरह से एक noop फ़ंक्शन को कॉल करने के बाद इसे अंदर डालने के बाद $q.when(angular.noop).then(function(){$state.go('myState'), सब कुछ अपेक्षित रूप से काम करता है। यदि मैं कॉल करता हूं, $state.goजबकि एक अन्य राज्य संक्रमण पूरा नहीं हुआ है, तो यह काम नहीं करेगा (मुझे लगता है कि यही कारण है कि यह काम नहीं करेगा)।
सेबेस्टियन

120

मेरी राय में अब तक पोस्ट किए गए समाधान अनावश्यक रूप से जटिल हैं। एक सरल तरीका है। के प्रलेखनui-router को सुनने का कहना है $locationChangeSuccessऔर उपयोग$urlRouter.sync() एक राज्य संक्रमण की जांच करने के लिए, यह पड़ाव है, या यह फिर से शुरू। लेकिन यह भी वास्तव में काम नहीं करता है।

हालांकि, यहां दो सरल विकल्प हैं। एक चुनें:

समाधान 1: सुन रहा है $locationChangeSuccess

आप सुन सकते हैं $locationChangeSuccessऔर आप कुछ तर्क कर सकते हैं, यहां तक ​​कि अतुल्यकालिक तर्क भी। उस तर्क के आधार पर, आप फ़ंक्शन को अपरिभाषित वापस कर सकते हैं, जो राज्य संक्रमण को सामान्य रूप से जारी रखने का कारण होगा, या आप कर सकते हैं $state.go('logInPage'), अगर उपयोगकर्ता को प्रमाणित करने की आवश्यकता है। यहाँ एक उदाहरण है:

angular.module('App', ['ui.router'])

// In the run phase of your Angular application  
.run(function($rootScope, user, $state) {

  // Listen to '$locationChangeSuccess', not '$stateChangeStart'
  $rootScope.$on('$locationChangeSuccess', function() {
    user
      .logIn()
      .catch(function() {
        // log-in promise failed. Redirect to log-in page.
        $state.go('logInPage')
      })
  })
})

ध्यान रखें कि यह वास्तव में लक्ष्य स्थिति को लोड होने से नहीं रोकता है, लेकिन यदि उपयोगकर्ता अनधिकृत है तो यह लॉग-इन पृष्ठ पर पुनर्निर्देशित करता है। यह ठीक है क्योंकि वास्तविक सुरक्षा सर्वर पर है, वैसे भी।

समाधान 2: राज्य का उपयोग करना resolve

इस समाधान में, आप ui-routerसमाधान सुविधा का उपयोग करते हैं

आप मूल रूप से वादा को अस्वीकार करते हैं resolveयदि उपयोगकर्ता प्रमाणित नहीं है और फिर उन्हें लॉग-इन पृष्ठ पर पुनर्निर्देशित करता है।

यहां बताया गया है:

angular.module('App', ['ui.router'])

.config(
  function($stateProvider) {
    $stateProvider
      .state('logInPage', {
        url: '/logInPage',
        templateUrl: 'sections/logInPage.html',
        controller: 'logInPageCtrl',
      })
      .state('myProtectedContent', {
        url: '/myProtectedContent',
        templateUrl: 'sections/myProtectedContent.html',
        controller: 'myProtectedContentCtrl',
        resolve: { authenticate: authenticate }
      })
      .state('alsoProtectedContent', {
        url: '/alsoProtectedContent',
        templateUrl: 'sections/alsoProtectedContent.html',
        controller: 'alsoProtectedContentCtrl',
        resolve: { authenticate: authenticate }
      })

    function authenticate($q, user, $state, $timeout) {
      if (user.isAuthenticated()) {
        // Resolve the promise successfully
        return $q.when()
      } else {
        // The next bit of code is asynchronously tricky.

        $timeout(function() {
          // This code runs after the authentication promise has been rejected.
          // Go to the log-in page
          $state.go('logInPage')
        })

        // Reject the authentication promise to prevent the state from loading
        return $q.reject()
      }
    }
  }
)

पहले समाधान के विपरीत, यह समाधान वास्तव में लक्ष्य स्थिति को लोड होने से रोकता है।


6
@FredLackey का कहना है कि अनधिकृत उपयोगकर्ता अंदर है state A। वे जाने के लिए एक लिंक पर क्लिक करते हैं, protected state Bलेकिन आप उन्हें पुनर्निर्देशित करना चाहते हैं logInPage। यदि कोई नहीं है $timeout, ui-routerतो बस सभी राज्य परिवर्तनों को रोक दिया जाएगा, इसलिए उपयोगकर्ता अंदर फंस जाएगा state A$timeoutकी अनुमति देता है ui-routerपहले करने के लिए प्रारंभिक संक्रमण को रोकने के लिए protected state B, क्योंकि संकल्प अस्वीकार कर दिया था और उसके बाद किया है, को रीडायरेक्ट logInPage
एमके सफ़ी

authenticateफ़ंक्शन को वास्तव में कहाँ कहा जाता है?
कोडीबस्टीन

@Imray authenticateफ़ंक्शन को पैरामीटर के रूप में पास किया जाता है ui-router। आपको इसे स्वयं कॉल करने की आवश्यकता नहीं है। ui-routerइसे कॉल करता है।
एमके सफी

आप '$ StateChangeStart' के बजाय '$ स्थान परिवर्तन' का उपयोग क्यों कर रहे हैं?
ड्रेक्स_

@ पीटरड्रेक्सड्रेक्सलर मैं ज्यादातर प्रलेखन का पालन कर रहा था। क्या आपने उपयोग करके कोई अंतर देखा $stateChangeStart?
MK Safi

42

सबसे आसान समाधान का उपयोग करना है $stateChangeStartऔर event.preventDefault()राज्य परिवर्तन रद्द जब उपयोगकर्ता प्रमाणीकृत नहीं है और करने के लिए उसे रीडायरेक्ट करने के लिए प्रमाणन राज्य प्रवेश पृष्ठ है।

angular
  .module('myApp', [
    'ui.router',
  ])
    .run(['$rootScope', 'User', '$state',
    function ($rootScope, User, $state) {
      $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        if (toState.name !== 'auth' && !User.authenticaded()) {
          event.preventDefault();
          $state.go('auth');
        }
      });
    }]
  );

6
मुझे नहीं लगता कि अगर User.authenticaded () एक async कॉल है तो यह काम करेगा। यही पवित्र कब्र सबके बाद है। उदाहरण के लिए, यदि "लॉगिन" को छोड़कर हर राज्य सुरक्षित है, तो मैं पुष्टि करना चाहता हूं कि उपयोगकर्ता अभी भी किसी भी राज्य को लोड करने से पहले प्रमाणित है । रिसॉल का उपयोग करना चूसता है क्योंकि वे केवल एक बार हल करते हैं, और बच्चे की स्थिति को लोड होने से रोकने के लिए, आपको संकल्प को हर जगह पर इंजेक्ट करना होगा ।
जेसन

प्रमाणीकृत मेरे मामले में एक async कॉल नहीं है: `this.authenticaded = function () {if (this.currentAccountID! == null) {वापसी सही; } विवरण झूठा है; }; `
3

प्रति के रूप में: stackoverflow.com/a/38374313/849829 , 'रन' सेवा की तरह ऊपर आता है और इसलिए समस्याएं हैं। प्रमाणित स्थिति के लिए स्थानीय स्तर की जाँच करना एक अच्छा तरीका है।
दीपक थॉमस

22

मुझे लगता है कि आपको serviceप्रमाणीकरण प्रक्रिया (और इसके भंडारण) को संभालने की आवश्यकता है ।

इस सेवा में आपको कुछ बुनियादी तरीकों की आवश्यकता होगी:

  • isAuthenticated()
  • login()
  • logout()
  • आदि ...

इस सेवा को प्रत्येक मॉड्यूल के अपने नियंत्रकों में इंजेक्ट किया जाना चाहिए:

  • अपने डैशबोर्ड अनुभाग में, यह जांचने के लिए कि उपयोगकर्ता प्रमाणित है ( service.isAuthenticated()विधि) इस सेवा का उपयोग करें । यदि नहीं, तो अनुप्रेषित / लॉगिन करें
  • अपने लॉगिन अनुभाग में, अपनी service.login()विधि के माध्यम से उपयोगकर्ता को प्रमाणित करने के लिए फ़ॉर्म डेटा का उपयोग करें

इस व्यवहार के लिए एक अच्छा और मजबूत उदाहरण परियोजना कोणीय-ऐप और विशेष रूप से इसका सुरक्षा मॉड्यूल है जो कि भयानक HTTP ई-कॉमर्स इंटरव्यू नियम पर आधारित है

उम्मीद है की यह मदद करेगा


21

मैंने इस मॉड्यूल को केक के इस प्रोसेस पीस को बनाने में मदद करने के लिए बनाया है

आप निम्न कार्य कर सकते हैं:

$routeProvider
  .state('secret',
    {
      ...
      permissions: {
        only: ['admin', 'god']
      }
    });

या भी

$routeProvider
  .state('userpanel',
    {
      ...
      permissions: {
        except: ['not-logged-in']
      }
    });

यह बिल्कुल नया है, लेकिन जांच के लायक है!

https://github.com/Narzerus/angular-permission


2
व्हाट्सएप मी रनिंग सोर्स को रनटाइम पर रोकने के लिए और आपके 'एडमिन' को हटाने के लिए || 'भगवान' और जारी?
पोग्रिंडिस

12
मुझे उम्मीद है कि किसी भी डेटा अनुरोधों को प्राधिकरण की आवश्यकता होती है जो सर्वर पर सत्यापित किए जा रहे हैं।
बेन रिप्ले

24
यह सुरक्षा के लिए नहीं है, ग्राहक-पक्षीय प्राधिकरण कभी नहीं है क्योंकि आप हमेशा मूल्यों को बदल सकते हैं। आप सर्वर की ओर से प्रतिक्रियाएं भी रोक सकते हैं और उन्हें "अधिकृत" के रूप में मूल्यांकन कर सकते हैं। क्लाइंट पक्ष में अनुमतियों / प्राधिकरण की बात यह है कि उपयोगकर्ता को औक्स प्रयोजनों के लिए निषिद्ध सामान करने से बचने के लिए है। उदाहरण के लिए यदि आप एक व्यवस्थापक-केवल कार्रवाई को संभाल रहे हैं, भले ही उपयोगकर्ता दुर्भावनापूर्ण रूप से क्लाइंट को सर्वर पर प्रतिबंधित अनुरोध भेजने की अनुमति देता हो, सर्वर अभी भी एक 401 प्रतिक्रिया लौटाएगा। यह वास्तव में पाठ्यक्रम हमेशा एपीआई की जिम्मेदारी कार्यान्वित किया जा रहा @BenRipley की है
राफेल Vidaurre

3
राफेल के सवाल पर शानदार प्रतिक्रिया। हमेशा एपी की सुरक्षा करें क्योंकि सामने वाला सबसे उल्टा इंजीनियर है, स्पूफ है।
फ्रेंकी लोसावियो

1
इतिहास के साथ यह समस्या काफी समय से हल हो रही है @Bohdan। आप इसे यूआई-राउटर एक्स्ट्रा के साथ भी सुरक्षित रूप से उपयोग कर सकते हैं।
मास्टर्सपैंम्बोट

16

मैं ui राउटर 1.0.0.X के साथ काम करने वाले एक अन्य समाधान को साझा करना चाहता था

जैसा कि आप जानते हैं, StateChangeStart और StateChangeSuccess अब पदावनत हो चुके हैं। https://github.com/angular-ui/ui-router/issues/2655

इसके बजाय आपको $ संक्रमण का उपयोग करना चाहिए http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html

मैंने इसे कैसे हासिल किया:

पहले मेरे पास और कुछ उपयोगी कार्यों के साथ AuthService है

angular.module('myApp')

        .factory('AuthService',
                ['$http', '$cookies', '$rootScope',
                    function ($http, $cookies, $rootScope) {
                        var service = {};

                        // Authenticates throug a rest service
                        service.authenticate = function (username, password, callback) {

                            $http.post('api/login', {username: username, password: password})
                                    .success(function (response) {
                                        callback(response);
                                    });
                        };

                        // Creates a cookie and set the Authorization header
                        service.setCredentials = function (response) {
                            $rootScope.globals = response.token;

                            $http.defaults.headers.common['Authorization'] = 'Bearer ' + response.token;
                            $cookies.put('globals', $rootScope.globals);
                        };

                        // Checks if it's authenticated
                        service.isAuthenticated = function() {
                            return !($cookies.get('globals') === undefined);
                        };

                        // Clear credentials when logout
                        service.clearCredentials = function () {
                            $rootScope.globals = undefined;
                            $cookies.remove('globals');
                            $http.defaults.headers.common.Authorization = 'Bearer ';
                        };

                        return service;
                    }]);

फिर मेरे पास यह कॉन्फ़िगरेशन है:

angular.module('myApp', [
    'ui.router',
    'ngCookies'
])
        .config(['$stateProvider', '$urlRouterProvider',
            function ($stateProvider, $urlRouterProvider) {
                $urlRouterProvider.otherwise('/resumen');
                $stateProvider
                        .state("dashboard", {
                            url: "/dashboard",
                            templateUrl: "partials/dashboard.html",
                            controller: "dashCtrl",
                            data: {
                                authRequired: true
                            }
                        })
                        .state("login", {
                            url: "/login",
                            templateUrl: "partials/login.html",
                            controller: "loginController"
                        })
            }])

        .run(['$rootScope', '$transitions', '$state', '$cookies', '$http', 'AuthService',
            function ($rootScope, $transitions, $state, $cookies, $http, AuthService) {

                // keep user logged in after page refresh
                $rootScope.globals = $cookies.get('globals') || {};
                $http.defaults.headers.common['Authorization'] = 'Bearer ' + $rootScope.globals;

                $transitions.onStart({
                    to: function (state) {
                        return state.data != null && state.data.authRequired === true;
                    }
                }, function () {
                    if (!AuthService.isAuthenticated()) {
                        return $state.target("login");
                    }
                });
            }]);

आप देख सकते हैं कि मैं उपयोग करता हूं

data: {
   authRequired: true
}

प्रमाणित होने पर ही राज्य को चिह्नित करना।

तो, पर .run मैं autheticated राज्य जाँच करने के लिए संक्रमण का उपयोग

$transitions.onStart({
    to: function (state) {
        return state.data != null && state.data.authRequired === true;
    }
}, function () {
    if (!AuthService.isAuthenticated()) {
        return $state.target("login");
    }
});

मैं इस उदाहरण का निर्माण $ संक्रमण दस्तावेज़ पर पाए गए कुछ कोड का उपयोग करके करता हूं। मैं ui राउटर के साथ बहुत नया हूं लेकिन यह काम करता है।

आशा है कि यह किसी को भी मदद कर सकता है।


नए राउटर का उपयोग करने वालों के लिए यह बहुत अच्छा है। धन्यवाद!
mtro

5

यहां बताया गया है कि कैसे हम अनंत मार्ग के पाश से बाहर निकले और अभी भी $state.goइसके बजाय इसका उपयोग किया जाता है$location.path

if('401' !== toState.name) {
  if (principal.isIdentityResolved()) authorization.authorize();
}

1
क्या किसी को पता होगा कि एड्रेस बार के ऊपर वर्णित स्वीकार किए गए उत्तर / सेटअप का उपयोग करते समय अब ​​url और सभी टुकड़े और क्वेरी स्ट्रिंग परम को प्रदर्शित नहीं करता है? इसे लागू करने के बाद से एड्रेस बार अब हमारे ऐप को बुकमार्क करने की अनुमति नहीं देता है।
फ्रेंकी लोसावियो

1
क्या यह मौजूदा उत्तरों में से किसी एक पर टिप्पणी करने वाला नहीं है? क्योंकि ओपी में ऐसा कोई कोड नहीं है और यह भी स्पष्ट नहीं है कि किस उत्तर / किस कोड का जिक्र है
TJ

3

मेरे पास एक और उपाय है: वह समाधान पूरी तरह से काम करता है जब आपके पास केवल वह सामग्री होती है जिसे आप लॉग इन करते समय दिखाना चाहते हैं। एक नियम को परिभाषित करें जहां आप जाँच रहे हैं कि क्या आप लॉग इन हैं और इसके श्वेतसूची मार्गों का नहीं।

$urlRouterProvider.rule(function ($injector, $location) {
   var UserService = $injector.get('UserService');
   var path = $location.path(), normalized = path.toLowerCase();

   if (!UserService.isLoggedIn() && path.indexOf('login') === -1) {
     $location.path('/login/signin');
   }
});

मेरे उदाहरण में मैं पूछता हूं कि क्या मैं लॉग इन नहीं हूं और वर्तमान रूट जिसे मैं रूट करना चाहता हूं वह `/ लॉगिन 'का हिस्सा नहीं है, क्योंकि मेरे श्वेतसूची मार्ग निम्नलिखित हैं

/login/signup // registering new user
/login/signin // login to app

इसलिए मेरे पास इस दो मार्गों की त्वरित पहुँच है और यदि आप ऑनलाइन हैं तो हर दूसरे मार्ग की जाँच की जाएगी।

यहाँ लॉगिन मॉड्यूल के लिए मेरी पूरी रूटिंग फ़ाइल है

export default (
  $stateProvider,
  $locationProvider,
  $urlRouterProvider
) => {

  $stateProvider.state('login', {
    parent: 'app',
    url: '/login',
    abstract: true,
    template: '<ui-view></ui-view>'
  })

  $stateProvider.state('signin', {
    parent: 'login',
    url: '/signin',
    template: '<login-signin-directive></login-signin-directive>'
  });

  $stateProvider.state('lock', {
    parent: 'login',
    url: '/lock',
    template: '<login-lock-directive></login-lock-directive>'
  });

  $stateProvider.state('signup', {
    parent: 'login',
    url: '/signup',
    template: '<login-signup-directive></login-signup-directive>'
  });

  $urlRouterProvider.rule(function ($injector, $location) {
    var UserService = $injector.get('UserService');
    var path = $location.path();

    if (!UserService.isLoggedIn() && path.indexOf('login') === -1) {
         $location.path('/login/signin');
    }
  });

  $urlRouterProvider.otherwise('/error/not-found');
}

() => { /* code */ } ES6 सिंटैक्स है, इसके बजाय उपयोग करें function() { /* code */ }


3

$ Http इंटरसेप्टर का उपयोग करें

$ Http इंटरसेप्टर का उपयोग करके आप हेडर को बैक-एंड या अन्य तरीके से भेज सकते हैं और इस तरह से अपने चेक कर सकते हैं।

$ Http इंटरसेप्टर्स पर शानदार लेख

उदाहरण:

$httpProvider.interceptors.push(function ($q) {
        return {
            'response': function (response) {

                // TODO Create check for user authentication. With every request send "headers" or do some other check
                return response;
            },
            'responseError': function (reject) {

                // Forbidden
                if(reject.status == 403) {
                    console.log('This page is forbidden.');
                    window.location = '/';
                // Unauthorized
                } else if(reject.status == 401) {
                    console.log("You're not authorized to view this page.");
                    window.location = '/';
                }

                return $q.reject(reject);
            }
        };
    });

इसे अपने .config या .run फ़ंक्शन में रखें।


2

सबसे पहले आपको एक सेवा की आवश्यकता होगी जिसे आप अपने नियंत्रकों में इंजेक्ट कर सकते हैं जिसमें एप्लिकेशन प्रमाणीकरण स्थिति का कुछ विचार है। स्थानीय भंडारण के साथ स्थायी विवरण जारी रखना एक अच्छा तरीका है।

अगला, आपको राज्य परिवर्तन से पहले अधिकार की स्थिति की जांच करने की आवश्यकता होगी। चूंकि आपके ऐप में कुछ ऐसे पृष्ठ हैं, जिन्हें प्रमाणित करने की आवश्यकता है और अन्य जो नहीं करते हैं, एक पेरेंट रूट बनाते हैं जो ऑक्टाकोर चेक करते हैं, और अन्य सभी ऐसे पेज बनाते हैं जिनके लिए उसी पैरेंट का बच्चा होना आवश्यक है।

अंत में, आपको यह बताने के लिए कुछ तरीके की आवश्यकता होगी कि क्या आपका वर्तमान में लॉग इन उपयोगकर्ता कुछ निश्चित कार्य कर सकता है। यह आपकी व्यावसायिक सेवा में 'कैन' फ़ंक्शन जोड़कर प्राप्त किया जा सकता है। दो पैरामीटर ले सकते हैं: - कार्रवाई - आवश्यक - (यानी 'manage_dashboards' या 'create_new_dashboard') - ऑब्जेक्ट - वैकल्पिक - ऑब्जेक्ट चालू किया जा रहा है। उदाहरण के लिए, यदि आपके पास एक डैशबोर्ड ऑब्जेक्ट है, तो आप यह देखने के लिए जांच कर सकते हैं कि डैशबोर्ड .ownerId === logInUser.id है या नहीं। (बेशक, क्लाइंट से प्राप्त जानकारी पर कभी भी भरोसा नहीं किया जाना चाहिए और आपको इसे अपने डेटाबेस में लिखने से पहले सर्वर पर हमेशा सत्यापित करना चाहिए)।

angular.module('myApp', ['ngStorage']).config([
   '$stateProvider',
function(
   $stateProvider
) {
   $stateProvider
     .state('home', {...}) //not authed
     .state('sign-up', {...}) //not authed
     .state('login', {...}) //not authed
     .state('authed', {...}) //authed, make all authed states children
     .state('authed.dashboard', {...})
}])
.service('context', [
   '$localStorage',
function(
   $localStorage
) {
   var _user = $localStorage.get('user');
   return {
      getUser: function() {
         return _user;
      },
      authed: function() {
         return (_user !== null);
      },
      // server should return some kind of token so the app 
      // can continue to load authenticated content without having to
      // re-authenticate each time
      login: function() {
         return $http.post('/login.json').then(function(reply) {
            if (reply.authenticated === true) {
               $localStorage.set(_userKey, reply.user);
            }
         });
      },
      // this request should expire that token, rendering it useless
      // for requests outside of this session
      logout: function() {
         return $http.post('logout.json').then(function(reply) {
            if (reply.authenticated === true) {
               $localStorage.set(_userKey, reply.user);
            }
         });
      },
      can: function(action, object) {
         if (!this.authed()) {
            return false;
         }

         var user = this.getUser();

         if (user && user.type === 'admin') {
             return true;
         }

         switch(action) {
            case 'manage_dashboards':
               return (user.type === 'manager');
         }

         return false;


      }
   }
}])
.controller('AuthCtrl', [
   'context', 
   '$scope', 
function(
   context, 
   $scope
) {
   $scope.$root.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
      //only require auth if we're moving to another authed page
      if (toState && toState.name.indexOf('authed') > -1) {
         requireAuth();
      }
   });

   function requireAuth() {
      if (!context.authed()) {
         $state.go('login');
      }
   }
}]

** अस्वीकरण: उपरोक्त कोड छद्म कोड है और बिना किसी गारंटी के आता है **

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.