AngularJS ইউআই-রাউটার লগইন প্রমাণীকরণ


376

আমি অ্যাঙ্গুলারজেএস-এ নতুন, এবং নিম্নলিখিত পরিস্থিতিতে আমি কীভাবে কৌনিক- "ইউআই-রাউটার" ব্যবহার করতে পারি তা সম্পর্কে আমি কিছুটা বিভ্রান্ত হয়ে পড়েছি:

আমি একটি ওয়েব অ্যাপ্লিকেশন তৈরি করছি যা দুটি বিভাগ নিয়ে গঠিত। প্রথম বিভাগটি এর লগইন এবং সাইনআপ দর্শন সহ হোমপেজ এবং দ্বিতীয় বিভাগটি ড্যাশবোর্ড (সফল লগইনের পরে)।

আমি index.htmlতার কৌণিক অ্যাপ্লিকেশন এবং ui-routerহ্যান্ডেল /loginএবং /signupদর্শনগুলি কনফিগার করে হোম বিভাগের জন্য একটি তৈরি করেছি dashboard.htmlএবং ড্যাশবোর্ড বিভাগের জন্য আরও একটি অ্যাপ্লিকেশন এবং ui-routerকনফিগারেশন সহ অনেকগুলি সাব ভিউ হ্যান্ডেল করার জন্য একটি ফাইল রয়েছে ।

এখন আমি ড্যাশবোর্ড বিভাগটি শেষ করেছি এবং কীভাবে দুটি বিভাগকে তাদের পৃথক কৌণিক অ্যাপ্লিকেশনগুলির সাথে একত্রিত করতে জানি না। আমি কীভাবে হোম অ্যাপটিকে ড্যাশবোর্ড অ্যাপে পুনর্নির্দেশ করতে বলতে পারি?


1
আপনি কি আমাদের সাথে কিছু কোড শেয়ার করতে পারেন?
চানচো

6
@ চ্যাঞ্চো আমি মনে করি এটি কোড সম্পর্কিত নয়, আসলে আমি জানি না আমার কী কোড ভাগ করা উচিত।
আহমেদ হাশেম

হ্যাঁ, দয়া করে কোডটি ভাগ করুন, খুব সাধারণ প্রশ্ন ...
আলিরাজা

উত্তর:


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। এটি আপনাকে বর্তমান অবস্থা, তারা যে রাজ্যে যেতে চায় সেগুলি পরীক্ষা করতে এবং আপনার অনুমোদনের চেক sertোকানোর সুযোগ দেয় gives যদি এটি ব্যর্থ হয়, আপনি রুট স্থানান্তর বাতিল করতে পারেন, বা অন্য কোনও রুটে পরিবর্তন করতে পারেন।

.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();
      });
    }
  ]);

যদি আপনি ইতিমধ্যে প্রমাণীকরণ করেছেন (বলুন, আপনি আগের সেশনের পরে পৃষ্ঠাটি পরিদর্শন করেছেন, এবং একটি কুকিতে একটি লেখক টোকেন সংরক্ষণ করেছেন, অথবা আপনি সম্ভবত কোনও পৃষ্ঠা সতেজ করে রেখেছেন, অথবা কোনও ব্যবহারকারীর পরিচয় সন্ধান করার কৌশলগত অংশটি এটির সন্ধান করছে) কোনও লিঙ্ক থেকে কোনও URL এ ফেলে দেওয়া হয়েছে)। যেভাবে 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(আপনি উত্তরাধিকার ব্যবহার করতে চান, অথবা তাদের একটি পিতা বা মাতা) এই রাজ্যের। এখানে, আমরা অ্যাডমিনগুলিতে একটি সংস্থান সীমাবদ্ধ করি:

.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
এটি দুর্দান্ত উত্তর এবং এটি আমাকে অনেক সাহায্য করেছে। যখন আমি আমার কন্ট্রোলারে ব্যবহারকারী = অধ্যক্ষ সেট করি এবং বর্তমানে ব্যবহারকারীর নামটি লগইন করার জন্য আমার মতে ইউডিআরসিডিটিটি () নামটি কল করার চেষ্টা করি তখন আমি কেবল প্রতিশ্রুতি অবজেক্টটি পাই বলে মনে করি {তারপরে: fn, ধরা: fn, অবশেষে :} প্রত্যাবর্তিত হয়েছে এবং প্রকৃত _ ঘটনাবস্তু বস্তু নয়। যদি আমি user.identity.then (fn (ব্যবহারকারী)) ব্যবহার করি তবে আমি ব্যবহারকারীর অবজেক্টটি পেতে পারি তবে এই ভিউটির জন্য অনেকগুলি কোডের মতো মনে হচ্ছে আমি কি কিছু মিস করছি?
চিহ্নিত করুন

4
@ ইর 1sh আমি কন্ট্রোলারে প্রথমে পরিচয়টি সমাধান করব এবং এটি $scope.userআপনার thenকার্যক্রমে নির্ধারিত করব । আপনি এখনও userআপনার দর্শনগুলিতে উল্লেখ করতে পারেন ; এটি সমাধান করা হলে, ভিউ আপডেট করা হবে।
moribvndvs

2
@ হ্যাকডবাইচিনিগুলি আমি মনে করি আপনার ডেমো আর কাজ করছে না।
ব্লুসি

7
@ জাভান্নিসটেলরোয় আমার যেতে () যেতে সমস্যা হয়েছে, তবে এটির পরে একটি নূপুর ফাংশনটি কল করার পরে $q.when(angular.noop).then(function(){$state.go('myState'), সবকিছু প্রত্যাশার মতো কাজ করে। যদি আমি $state.goঅন্য কল্যাণীয় রূপান্তর সম্পন্ন না হয়ে কল করি তবে তা কার্যকর হবে না (আমি মনে করি এটি সে কারণেই কাজ করবে না)।
সেবাস্তিয়ান

120

আমার মতে, এখনও অবধি পোস্ট করা সমাধানগুলি অযথা জটিল। একটি সহজ উপায় আছে। ডকুমেন্টেশনui-router কথা শুনতে বলছেন $locationChangeSuccessএবং ব্যবহারের $urlRouter.sync()একটি রাষ্ট্র রূপান্তরটি চেক করতে, এটা বন্ধ, অথবা এটি পুনরায় শুরু করুন। কিন্তু এটি আসলে কাজ করে না।

তবে, এখানে দুটি সহজ বিকল্প রয়েছে are একটা তোল:

সমাধান 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
@ ফ্রেডল্যাকি বলছেন অচিহ্নিত ব্যবহারকারী রয়েছেন state A। তারা যেতে একটি লিঙ্ক ক্লিক করে protected state Bতবে আপনি এগুলিতে পুনর্নির্দেশ করতে চান logInPage। যদি না থাকে $timeout, ui-routerকেবল সমস্ত রাষ্ট্রীয় রূপান্তর বন্ধ করে দেবে, তাই ব্যবহারকারী আটকে থাকবে state A$timeoutপারবেন ui-routerপ্রথম প্রাথমিক রূপান্তরটি প্রতিরোধ protected state Bকারণ সমাধানে প্রত্যাখ্যাত হয়েছিল এবং পরে যে কাজ করছে, এটি পুননির্দেশনা logInPage
এম কে সাফি

authenticateফাংশনটি আসলে কোথায় বলা হয়?
কোডি বাগস্টাইন

@ ইম্রে authenticateফাংশনটি প্যারামিটার হিসাবে পাস করা হয়েছে ui-router। আপনার নিজের এটি কল করতে হবে না। ui-routerএটি কল।
এমকে সাফি

আপনি কেন '$ stateChangeStart' এর পরিবর্তে '$ লোকেশন চেঞ্জসুসেসি' ব্যবহার করছেন?
ড্রেক্স_আগস্ট

@ পিটারড্রেক্সড্রাক্সলার আমি বেশিরভাগ ডকুমেন্টেশন অনুসরণ করছিলাম। আপনি ব্যবহার করে কোন পার্থক্য লক্ষ্য করেছেন $stateChangeStart?
এমকে সাফি

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
আমি মনে করি না যদি ইউজার.আউটিক্যান্টেড () একটি অ্যাসিঙ্ক কল হয় তবে এটি কাজ করবে। এটাই পবিত্র কচুর। উদাহরণস্বরূপ, "লগইন" ব্যতীত প্রতিটি রাজ্য যদি সুরক্ষিত হয় তবে আমি নিশ্চিত করতে চাই যে কোনও রাজ্য লোড করার আগে ব্যবহারকারী এখনও প্রমাণীকৃত । সমাধানগুলি সাফল্যগুলি ব্যবহার করে কারণ তারা কেবল একবারই সমাধান করে এবং শিশুদের রাষ্ট্রগুলি বোঝা বাধা দেওয়ার জন্য, আপনাকে প্রতিটি বাচ্চার মধ্যে এই সংকল্পটি ইনজেক্ট করতে হবে ।
জেসন

সত্যায়িত হওয়া আমার ক্ষেত্রে একটি অ্যাসিঙ্ক কল নয়: `this.authenticaded = ফাংশন () {যদি (this.currentAccountID! == নাল) {সত্য প্রত্যাবর্তন; false মিথ্যা প্রত্যাবর্তন; }; `
sebest

স্ট্যাকওভারফ্লো.com / a / 38374313 / 849829 অনুসারে , 'রান' পরিষেবাটির উপরে চলে আসে এবং সে কারণে সমস্যাগুলি। প্রত্যয়িত স্থিতির জন্য লোকালস্টোরেজ চেক করা একটি ভাল পদ্ধতির বলে মনে হচ্ছে।
দীপক থমাস

22

আমি মনে করি আপনার serviceএমন একটি দরকার যা প্রমাণীকরণ প্রক্রিয়া পরিচালনা করে (এবং এর সঞ্চয়স্থান)।

এই পরিষেবাটিতে আপনার কয়েকটি প্রাথমিক পদ্ধতি প্রয়োজন:

  • isAuthenticated()
  • login()
  • logout()
  • ইত্যাদি ...

এই পরিষেবাটি প্রতিটি মডিউলের আপনার নিয়ামকদের ইনজেকশন করা উচিত:

  • আপনার ড্যাশবোর্ড বিভাগে, এই পরিষেবাটি ব্যবহারকারীর অনুমোদনযোগ্য ( service.isAuthenticated()পদ্ধতি) কিনা তা পরীক্ষা করতে ব্যবহার করুন । যদি তা না হয় তবে / লগইনে পুনর্নির্দেশ করুন
  • আপনার লগইন বিভাগে, আপনার service.login()পদ্ধতির মাধ্যমে ব্যবহারকারীকে প্রমাণীকরণ করতে কেবল ফর্ম ডেটা ব্যবহার করুন

এই আচরণের জন্য একটি ভাল এবং দৃust় উদাহরণ হ'ল প্রকল্পের কৌণিক অ্যাপ্লিকেশন এবং বিশেষত এর সুরক্ষা মডিউল যা দুর্দান্ত এইচটিটিপি আথ ইন্টারসেপ্টর মডিউলটির উপর ভিত্তি করে তৈরি

আশাকরি এটা সাহায্য করবে


21

এই প্রক্রিয়াটিকে কেকের টুকরো তৈরি করতে সহায়তা করার জন্য আমি এই মডিউলটি তৈরি করেছি

আপনি যেমন কাজ করতে পারেন:

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

বা এছাড়াও

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

এটি একেবারে নতুন তবে চেক আউট মূল্য!

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


2
রানটাইমের সময় আমাকে উত্স সম্পাদনা করা এবং আপনার 'প্রশাসক' মুছে ফেলার জন্য কী আছে || 'godশ্বর' এবং অবিরত?
পোগরিন্ডিস

12
আমি আশা করব যে কোনও ডেটা অনুরোধের জন্য যা অনুমোদনের প্রয়োজন রয়েছে সেগুলিও সার্ভারে যাচাই করা হচ্ছে।
বেন রিপলে

24
এটি সুরক্ষার জন্য নয়, ক্লায়েন্ট-পার্শ্বযুক্ত অনুমোদন কখনই হয় না কারণ আপনি সর্বদা মান পরিবর্তন করতে পারেন। এমনকি আপনি সার্ভারের পক্ষ থেকে প্রতিক্রিয়াগুলি বাধা দিতে এবং তাদেরকে "অনুমোদিত" হিসাবে মূল্যায়ন করতে পারবেন ক্লায়েন্টের পক্ষের অনুমতি / অনুমোদনের বিষয়টি হ'ল ইউএক্স উদ্দেশ্যে ব্যবহারকারীকে নিষিদ্ধ জিনিস না দেওয়া এড়ানো। উদাহরণস্বরূপ, যদি আপনি কেবল প্রশাসক-অ্যাকশনটি পরিচালনা করছেন, এমনকি ব্যবহারকারী যদি ক্লায়েন্টকে সার্ভারে একটি সীমাবদ্ধ অনুরোধ প্রেরণের অনুমতি দেওয়ার জন্য ক্ষতিকারকভাবে চালিত করে, সার্ভারটি এখনও 401 প্রতিক্রিয়া ফিরিয়ে আনবে। এটি অবশ্যই বেন রিপলে বাস্তবায়িত হবার এপিআইর দায়বদ্ধতা
রাফায়েল ভিদুরে

3
রাফায়েল প্রশ্নে দুর্দান্ত প্রতিক্রিয়া। সর্বদা এপিকে রক্ষা করুন কারণ ফ্রন্ট-এন্ডটি সবচেয়ে বিপরীত ইঞ্জিনিয়ারিং, স্পোফেবল জিনিস there
ফ্র্যাঙ্কি লসকাভিও

1
ইতিহাস নিয়ে এই সমস্যার সমাধান এখন বেশ কয়েকটি সময়ের জন্য @ বোহদান। আপনি ইউআই রাউটার অতিরিক্ত দিয়েও নিরাপদে এটি ব্যবহার করতে পারেন।
মাস্টারস্পামবট

16

আমি ইউআই রাউটার 1.0.0.X এর সাথে কাজ করে আরেকটি সমাধান ভাগ করতে চেয়েছিলাম

আপনারা জানেন যে, স্টেট চ্যাঞ্জস্টার্ট এবং স্টেট চ্যাঞ্জসুসেস এখন অবচিত করা হয়েছে। 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

এইভাবেই আমি এটি অর্জন করেছি:

প্রথমে আমার কাছে আছে এবং কিছু কার্যকর ফাংশন সহ অথথ সার্ভিস

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
}

রাজ্যটিকে কেবলমাত্র অ্যাক্সেসযোগ্য যদি চিহ্নিত করা হয় তবে চিহ্নিত করতে।

তারপরে .আরুন-এ আমি স্বীকৃত স্থিতি পরীক্ষা করতে রূপান্তরগুলি ব্যবহার করি

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

আমি example ট্রানজিশন ডকুমেন্টেশনে পাওয়া কিছু কোড ব্যবহার করে এই উদাহরণটি তৈরি করি। আমি ইউআই রাউটারের সাথে বেশ নতুন কিন্তু এটি কার্যকর।

আশা করি এটি যে কাউকে সহায়তা করতে পারে।


যারা নতুন রাউটার ব্যবহার করছেন তাদের পক্ষে এটি দুর্দান্ত is ধন্যবাদ!
এমট্রো

5

আমরা কীভাবে অসীম রাউটিং লুপটি থেকে বেরিয়ে এসেছি এবং এর $state.goপরিবর্তে এখনও ব্যবহার করেছি$location.path

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

1
কেউ জানতে পারবেন কেন ঠিকানা বারের উপরে বর্ণিত স্বীকৃত উত্তর / সেটআপ ব্যবহার করার পরে আর ইউআরএল এবং সমস্ত টুকরোগুলি এবং কোয়েরি স্ট্রিং প্যারামগুলি প্রদর্শিত হবে না? এটি কার্যকর করার পরে ঠিকানা বারটি আর আমাদের অ্যাপ্লিকেশনটিকে বুকমার্ক করার অনুমতি দেয় না।
ফ্র্যাঙ্কি লসকাভিও

1
এটি কি বিদ্যমান উত্তরের একটি মন্তব্য বলে মনে করা হচ্ছে না? কারণ ওপিতে এ জাতীয় কোনও কোড নেই এবং এটি কোন উত্তর / কী কোডটি উল্লেখ করছে তাও পরিষ্কার নয়
টিজে

3

আমার আরও একটি সমাধান রয়েছে: আপনি যখন লগইন করবেন তখন আপনি কেবলমাত্র সেই বিষয়বস্তু প্রদর্শন করতে চান যখন সমাধানটি পুরোপুরি কার্যকর হয় you আপনি লগ ইন করেছেন কিনা তা পরীক্ষা করে কোনও নিয়ম নির্ধারণ করুন এবং এটি শ্বেতলিস্টের পথে নয় path

$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

প্রথমে আপনার এমন একটি পরিষেবা প্রয়োজন যা আপনি আপনার নিয়ন্ত্রকদের ইনজেক্ট করতে পারেন যা অ্যাপ্লিকেশন অনুমোদনের স্থিতির কিছু ধারণা রয়েছে। স্থানীয় স্টোরেজ সহ লেখকের বিশদ বিশিষ্ট করা এটির কাছে যাওয়ার একটি শালীন উপায়।

এরপরে, আপনাকে রাষ্ট্র পরিবর্তনের ঠিক আগে লেখকের অবস্থা পরীক্ষা করতে হবে। যেহেতু আপনার অ্যাপ্লিকেশনটিতে এমন কিছু পৃষ্ঠা রয়েছে যাগুলির প্রমাণীকরণের প্রয়োজন হয় এবং অন্যগুলি যা না করে, এমন কোনও প্যারেন্ট রুট তৈরি করে যা লেখককে পরীক্ষা করে এবং অন্য সমস্ত পৃষ্ঠাগুলিকে সেই পিতামাতার সন্তানের মতো করা দরকার।

অবশেষে, আপনার বর্তমানে লগ ইন করা ব্যবহারকারী নির্দিষ্ট ক্রিয়াকলাপ সম্পাদন করতে পারেন কিনা তা জানানোর জন্য আপনাকে কিছু উপায়ের প্রয়োজন হবে। আপনার লেখক পরিষেবাতে একটি 'ক্যান' ফাংশন যুক্ত করে এটি অর্জন করা যেতে পারে। দুটি প্যারামিটার লাগতে পারে: - ক্রিয়া - প্রয়োজনীয় - (যেমন 'ম্যানেজ_ড্যাশবোর্ড' বা 'create_new_dashboard') - অবজেক্ট - alচ্ছিক - অবজেক্টটিতে কাজ করা হচ্ছে। উদাহরণস্বরূপ, আপনার যদি ড্যাশবোর্ড অবজেক্ট থাকে তবে আপনি dashboard.ownerId === loginInUser.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');
      }
   }
}]

** অস্বীকৃতি: উপরের কোডটি সিউডো কোড এবং কোনও গ্যারান্টি সহ আসে না **

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.