آموزش گام به گام AngularJS قسمت دهم : Login و Validation

بازدید کنندگان : 2451 دسته بندی برنامه نویسی , برنامه نویسی سمت کلاینت , شروع کار با AngularJS
در مقالات قبل با نحوه ساخت Service و Factory  و همچنین ngRoute و ng-view آشنا شدیم
در این مقاله قصد داریم یک صفحه لاگین به پروژه قبلی اضافه کنیم به نحوی که فقط در صورتی که تشخیص هویت انجام شد کاربر قادر به مشاهده صفحات دیگر باشد .
در این مقاله ما یک درخواست Ajax به یک آدرس جهت تشخیص هویت ارسال می کنیم که حاوی نام کاربری و رمز عبور است ، سپس در پاسخ یک Token ایجاد شده و در اختیار ما قرار میگیرد ، از آن به بعد تمامی درخواست های دیگر از طریق این رمز یکبار مصرف انجام خواهد شد .
برای ذخیره این Token چند روش وجود دارد ، یکی از آنها روش قدیمی Cookie است ولی ما در این مقاله از ngStorage برای ذخیره اطلاعات استفاده می کنیم .
ngStorage اطلاعات را در Local Storage مرورگر ذخیره کرده و آن را واکشی و مدیریت میکند ، کافیست کتابخانه ngStorage را اضافه کرده و به خیلی ساده از طریق سرویس $localStorage آن را مقدار دهی کنید ، در این مقاله اطلاعات کاربر شامل رمز یکبارمصرف و غیره داخل متغیر userData در Local Storage ذخیره خواهد شد .
برای شروع کار ابتدا یک صفحه لاگین ایجاد کرده یک فایل Controller نیز برای آن ایجاد نموده و مسیر را در app.config تنظیم می نماییم
یک سرویس یا فکتوری به نام LoginService ایجاد کرده و متدهایی برای login و logout در آن ایجاد می کنیم :
app.service('loginServices', function ($rootScope, $http, $location, $localStorage) { 
 
    this.Load = function () { 
        if ($localStorage.userData) { 
            $rootScope.isAuthenticate = true; 
        } 
    } 
 
    this.Login = function (loginData) { 
 
        $http({ 
            method: "GET", 
            url: '/UserData/Auth/', 
            params: loginData 
        }).then(function mySucces(response) { 
 
            $localStorage.userData = response.data[0]; 
 
            if ($localStorage.userData.token) { 
 
                $rootScope.isAuthenticate = true; 
                $location.path('/display'); 
 
            } 
            else { 
 
                alert('wrong password'); 
            } 
 
 
        }, function myError(response) { 
            alert('Error:' + response.statusText); 
        }); 
 
    } 
 
    this.LogOut = function () { 
 
        delete $localStorage.userData; 
        $rootScope.isAuthenticate = false; 
        $location.path('/login'); 
 
    } 
 
}); 
همانطور که ملاحظه می کنید 3 متد در این سرویس تعریف کرده ام ، متد اول Load چک میکند که اگر اطلاعاتی داخل متغیر 
userData وجود داشت مقدار isAuthenticate که یک متغیر در rootScope است را true کند 
متد Login یک درخواست http از نوع Get به آدرس مورد نظر حاوی اطلاعات loginData ارسال میکند ( در زیر به نحوه مقدار 
دهی loginData را ملاحظه خواهد کرد ) و مقدار پاسخ را در userData ذخیره میکند ، سپس چک میکنیم اگر این مقدار حاوی 
token مورد نظر بود مقدار isAuthenticate را true کرده و سپس کاربر را به صفحه display هدایت خواهیم کرد در غیر این 
صورت پیغام مبنی بر اشتباه بودن رمز نمایش داده میشود . 
و در نهایت متد LogOut که ابتدا userData را حذف کرده ، مقدار isAuthenticate را false میکنیم وسپس  کاربر را به صفحه 
login  هدایت مینماییم . 
اکنون که این سرویس را ایجاد کردیم به سراغ صفحه لاگین برویم ، یک فرم خیلی ساده شامل نام کاربری و رمز عبور ایجاد کرده و 
فیلدهارا مدل کنید ، سپس در کنترلر مربوط به لاگین خواهیم داشت :
 
app.controller('loginCtrl', function ($scope, loginServices) { 
    $scope.login = function () { 
 
        var loginData = { 
            userName: $scope.user, 
            password: $scope.pass 
        }; 
 
        loginServices.Login(loginData); 
    }; 
 
}); 


کدها خیلی ساده و خلاصه هستند ، ما loginService را در ورودی تابع کنترل معرفی کردیم و یک آرایه jSON به نام login ایجاد 
کردیم و مقادیر مورد نظر را به آن تخصیص دادیم ، سپس متد Login در loginService را با ورودی این مقادیر فراخوانی کردیم . 
اگر اطلاعات صحیح باشد کاربر به صفحه display هدایت خواهد شد 
تنها یک مشکل باقی است ، اگر کاربر مستقیما صفحه display را فرخوانی کند چه اتفاقی می افتد ؟  
بله صفحه display نمایش داده خواهد شد ، البته میتوانیم در هریک از کنترلرها ( مثلا display ) به صورت دستی چک کنیم که آیا  
کاربر isAuthenticate هست یا خیر ولی این روش خیلی اصولی و مدرن نیست ( روش asp classic است ) 
برای جلوگیری از این مشکل انگولار یک سرویس به نا on قرار داده است که میتواند event های مختلف را مدیریت نماید .
    $rootScope.$on('$locationChangeStart', function (event, next, current) { 
         
        if (!$rootScope.isAuthenticate) { 
            $location.path('/login'); 
        } 
    }); 
در کد زیر از سرویس on داخل rooScope استفاده شده است تا رویداد locationChangeStart مدیریت شود 
یعنی هربار که رویداد locationChangeStart رخ میدهد این تابع اجرا میگردد و در این تابع ما چک میکنیم اگر کاربر تشخیص 
هویت نشده بود به صفحه login هدایتش خواهیم کرد . 
ورودی های event,next و current اطلاعات جامعی راجع به رویداد و path های فعلی و قبلی در اختیار ما قرار میدهند. 
بلاک کد فوق را در فایل Application.js و متد app.run قرار میدهیم در نهایت فایل Application ما به شکل زیر خواهد بود :
var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'ngStorage', 'angular-loading-bar']); 
 
app.run(function ($rootScope, $location, loginServices, userServices) { 
    $rootScope.myData; 
    $rootScope.isAuthenticate 
    userServices.Fetch().then(function (response) { 
        $rootScope.myData = response.data; 
    }); 
 
    loginServices.Load(); 
    $rootScope.logOut = function () { 
 
        loginServices.LogOut(); 
    } 
 
    $rootScope.$on('$locationChangeStart', function (event, next, current) { 
         
        if (!$rootScope.isAuthenticate) { 
            $location.path('/login'); 
        } 
    }); 
 
}); 
 
 
app.config(function ($routeProvider, cfpLoadingBarProvider) { 
 
 
    cfpLoadingBarProvider.includeSpinner = false; 
 
    $routeProvider.when('/display', { 
        templateUrl: '/Application/Views/Grid.html', 
        controller: 'gridCtrl' 
    }) 
    .when('/add', { 
        templateUrl: '/Application/Views/Form.html', 
        controller: 'formCtrl' 
    }) 
    .when('/edit/:id', { 
        templateUrl: '/Application/Views/Edit.html', 
        controller: 'editCtrl' 
    }) 
    .when('/login', { 
        templateUrl: '/Application/Views/Login.html', 
        controller: 'loginCtrl' 
    }) 
    .otherwise({ 
        redirectTo: '/display' 
    }); 
 
در این پروژه از ngAnimate و ngLoadingBar استفاده شده است که در مقاله بعدی توضیح داده خواهد شد
برای فهم بهتر مطلب حتما فایل پروژه را ا اینجا  دانلود و ملاحظه نمایید

منابع :

نظرات کاربران