AngularJS: Contoh dasar untuk menggunakan otentikasi dalam Aplikasi Halaman Tunggal

100

Saya baru mengenal AngularJS dan telah melalui tutorial mereka dan merasakannya.

Saya memiliki backend untuk proyek saya yang siap di mana masing-masing RESTtitik akhir perlu diautentikasi.

Apa yang ingin saya lakukan
a.) Saya ingin memiliki satu halaman untuk proyek saya http://myproject.com.
b.) Setelah pengguna menekan URL di browser, berdasarkan apakah pengguna masuk atau tidak, dia disajikan dengan halaman beranda / tampilan atau halaman login / tampilan di bawah url yang sama http://myproject.com.
c.) jika pengguna tidak masuk, itu mengisi formulir dan server menetapkan USER_TOKENsesi dalam, sehingga semua permintaan lebih lanjut ke titik akhir akan diautentikasi berdasarkanUSER_TOKEN

Kebingungan Saya
a.) Bagaimana cara menangani otentikasi sisi klien menggunakan AngularJS? Saya melihat di sini dan di sini tetapi tidak mengerti cara menggunakannya
b.) Bagaimana saya bisa menyajikan tampilan berbeda kepada pengguna berdasarkan apakah pengguna masuk atau tidak di bawah url yang samahttp://myproject.com

Saya menggunakan angular.js untuk pertama kalinya dan benar-benar bingung bagaimana memulainya. Setiap saran dan / atau sumber sangat dihargai.

pelamun
sumber
Silakan lihat artikel di bawah frederiknakstad.com/…
Ajay Beniwal
1
@MichaelCalkins hanya menempatkan tautan tidak membangun. Anda setidaknya harus mengatakan apa yang akan diberikan tautan tersebut.
Dave Gordon
My b: AngularJS Access Control and Authentication coderwall.com/p/f6brkg
Michael J. Calkins
Tim di OAuth memiliki perpustakaan yang bagus untuk andreareginato.github.io/oauth-ng
Faktor 10

Jawaban:

48

Saya telah membuat repo github yang merangkum artikel ini pada dasarnya: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login repo Github

Plunker

Saya akan mencoba menjelaskan sebaik mungkin, semoga saya membantu beberapa dari Anda di luar sana:

(1) app.js: Pembuatan konstanta autentikasi pada definisi aplikasi

var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
    all : '*',
    admin : 'admin',
    editor : 'editor',
    guest : 'guest'
}).constant('AUTH_EVENTS', {
    loginSuccess : 'auth-login-success',
    loginFailed : 'auth-login-failed',
    logoutSuccess : 'auth-logout-success',
    sessionTimeout : 'auth-session-timeout',
    notAuthenticated : 'auth-not-authenticated',
    notAuthorized : 'auth-not-authorized'
})

(2) Layanan Auth: Semua fungsi berikut diimplementasikan dalam layanan auth.js. Layanan $ http digunakan untuk berkomunikasi dengan server untuk prosedur otentikasi. Juga berisi fungsi tentang otorisasi, yaitu jika pengguna diizinkan untuk melakukan tindakan tertentu.

angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS', 
function($http, $rootScope, $window, Session, AUTH_EVENTS) {

authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]

return authService;
} ]);

(3) Sesi: Singleton untuk menyimpan data pengguna. Penerapannya di sini bergantung pada Anda.

angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {

    this.create = function(user) {
        this.user = user;
        this.userRole = user.userRole;
    };
    this.destroy = function() {
        this.user = null;
        this.userRole = null;
    };
    return this;
});

(4) Pengontrol induk: Anggap ini sebagai fungsi "utama" aplikasi Anda, semua pengontrol mewarisi dari pengontrol ini, dan ini adalah tulang punggung autentikasi aplikasi ini.

<body ng-controller="ParentController">
[...]
</body>

(5) Kontrol akses: Untuk menolak akses pada rute tertentu, 2 langkah harus dilaksanakan:

a) Tambahkan data dari peran yang diizinkan untuk mengakses setiap rute, pada layanan $ stateProvider ui router seperti yang dapat dilihat di bawah (hal yang sama dapat bekerja untuk ngRoute).

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b) Di $ rootScope. $ on ('$ stateChangeStart') tambahkan fungsi untuk mencegah perubahan status jika pengguna tidak diizinkan.

$rootScope.$on('$stateChangeStart', function (event, next) {
    var authorizedRoles = next.data.authorizedRoles;
    if (!Auth.isAuthorized(authorizedRoles)) {
      event.preventDefault();
      if (Auth.isAuthenticated()) {
        // user is not allowed
        $rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
      } else {
        // user is not logged in
        $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
      }
    }
});

(6) Pencegat auth: Ini diterapkan, tetapi tidak dapat diperiksa pada cakupan kode ini. Setelah setiap permintaan $ http, interseptor ini memeriksa kode status, jika salah satu dari di bawah ini dikembalikan, maka ia menyiarkan acara untuk memaksa pengguna untuk masuk lagi.

angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
    return {
        responseError : function(response) {
            $rootScope.$broadcast({
                401 : AUTH_EVENTS.notAuthenticated,
                403 : AUTH_EVENTS.notAuthorized,
                419 : AUTH_EVENTS.sessionTimeout,
                440 : AUTH_EVENTS.sessionTimeout
            }[response.status], response);
            return $q.reject(response);
        }
    };
} ]);

PS Bug dengan form data autofill seperti yang tertera pada artikel pertama dapat dengan mudah dihindari dengan menambahkan direktif yang terdapat pada directives.js.

PS2 Kode ini dapat dengan mudah diubah oleh pengguna, untuk memungkinkan rute yang berbeda untuk dilihat, atau menampilkan konten yang tidak dimaksudkan untuk ditampilkan. Logika HARUS diterapkan di sisi server, ini hanyalah cara untuk menampilkan berbagai hal dengan benar di aplikasi ng Anda.

Alex Arvanitidis
sumber
1
Saya telah mengikuti panduan Anda untuk memahami logika sisi klien. Itu sangat bagus!! Saya melewatkan sesuatu tentang penghancuran sesi secara manual, tetapi kami harus bereksperimen dan juga merusak!
Sebastialonso
~~ tidak yakin apakah saya benar-benar memahami baris itu: authService.login() = [...]tanda kurung siku itu akan mewakili sesuatu seperti $http.get(url, {uID, pwd}? ~~ ok, lihat ke plunker, seperti yang saya katakan XD
netalex
1
dapatkah Anda memperluas jawaban Anda untuk sisi server?
kueri
25

Saya suka pendekatannya dan menerapkannya di sisi server tanpa melakukan hal apa pun yang terkait dengan otentikasi di front-end

'Teknik' saya di aplikasi terbaru saya adalah .. klien tidak peduli dengan Auth. Setiap hal dalam aplikasi membutuhkan login terlebih dahulu, jadi server selalu menyajikan halaman login kecuali pengguna yang ada terdeteksi dalam sesi tersebut. Jika session.user ditemukan, server hanya mengirim index.html. Bam: -o

Carilah komentar dari "Andrew Joslin".

https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ

pelamun
sumber
3
apakah itu api web? Saya tidak mendapatkan jawaban Anda, saya kira :(
Leandro De Mello Fagundes
1
Bagaimana jika Anda ingin menampilkan username? Atau jika Anda berbicara ke layanan dengan nama pengguna di URL titik akhir?
perrygeo
2
maaf, tapi saya tidak mengerti jawabannya. bagaimana Anda menangani sesi dalam sudut? dimana session.user ditetapkan? Bisakah Anda membuat contoh kode ini? terima kasih
François Romain
4
Sesi ditangani di sisi klien dan bukan di sisi server, klien menyimpan token dan mengirimkannya sebagai bagian dari setiap permintaan yang dibuatnya. Server memvalidasi token dan memproses permintaan
daydreamer
4
Bisakah seseorang yang memahaminya mengedit jawaban ini untuk kita semua?
Alojz Janez
14

Saya menjawab pertanyaan serupa di sini: AngularJS Authentication + RESTful API


Saya telah menulis modul AngularJS untuk UserApp yang mendukung rute dilindungi / publik, perutean ulang saat masuk / keluar, detak jantung untuk pemeriksaan status, menyimpan token sesi dalam cookie, acara, dll.

Anda bisa:

  1. Ubah modul dan lampirkan ke API Anda sendiri, atau
  2. Gunakan modul bersama dengan UserApp (API manajemen pengguna berbasis cloud)

https://github.com/userapp-io/userapp-angular

Jika Anda menggunakan UserApp, Anda tidak perlu menulis kode sisi server apa pun untuk barang-barang pengguna (lebih dari memvalidasi token). Ikuti kursus di Codecademy untuk mencobanya.

Berikut beberapa contoh cara kerjanya:

  • Cara menentukan rute mana yang harus publik, dan rute mana yang merupakan formulir login:

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
    $routeProvider.when('/home', {templateUrl: 'partials/home.html'});

    The .otherwise()rute harus ditetapkan ke mana Anda ingin pengguna Anda akan diarahkan setelah login. Contoh:

    $routeProvider.otherwise({redirectTo: '/home'});

  • Formulir login dengan penanganan error:

    <form ua-login ua-error="error-msg">
        <input name="login" placeholder="Username"><br>
        <input name="password" placeholder="Password" type="password"><br>
        <button type="submit">Log in</button>
        <p id="error-msg"></p>
    </form>
  • Formulir pendaftaran dengan penanganan kesalahan:

    <form ua-signup ua-error="error-msg">
      <input name="first_name" placeholder="Your name"><br>
      <input name="login" ua-is-email placeholder="Email"><br>
      <input name="password" placeholder="Password" type="password"><br>
      <button type="submit">Create account</button>
      <p id="error-msg"></p>
    </form>
  • Tautan keluar:

    <a href="#" ua-logout>Log Out</a>

    (Mengakhiri sesi dan dialihkan ke rute login)

  • Akses properti pengguna:

    Properti pengguna diakses menggunakan userlayanan, misalnya:user.current.email

    Atau di template: <span>{{ user.email }}</span>

  • Sembunyikan elemen yang seharusnya hanya terlihat saat masuk:

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • Tunjukkan elemen berdasarkan izin:

    <div ua-has-permission="admin">You are an admin</div>

Dan untuk mengotentikasi ke layanan back-end Anda, cukup gunakan user.token()untuk mendapatkan token sesi dan kirimkan dengan permintaan AJAX. Di bagian belakang, gunakan UserApp API (jika Anda menggunakan UserApp) untuk memeriksa apakah token itu valid atau tidak.

Jika Anda butuh bantuan, beri tahu saya!

Timothy E. Johansson
sumber
Bagaimana saya akan "Mengubah modul dan melampirkannya ke API Anda sendiri" ?
Pureferret
2

Di angularjs Anda dapat membuat bagian UI, layanan, Direktif, dan semua bagian dari angularjs yang mewakili UI. Ini adalah teknologi yang bagus untuk dikerjakan.

Sebagai orang yang baru mengenal teknologi ini dan ingin mengotentikasi "Pengguna" maka saya sarankan untuk melakukannya dengan kekuatan api web c #. untuk itu, Anda dapat menggunakan spesifikasi OAuth yang akan membantu Anda membangun mekanisme keamanan yang kuat untuk mengautentikasi pengguna. setelah Anda membangun WebApi dengan OAuth, Anda perlu memanggil api itu untuk token:

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

dan setelah Anda mendapatkan token maka Anda meminta sumber daya dari angularjs dengan bantuan Token dan mengakses sumber daya yang disimpan aman di Api web dengan spesifikasi OAuth.

Silakan lihat artikel di bawah ini untuk bantuan lebih lanjut: -

http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/

Gurupreet
sumber
1

Saya berpikir bahwa setiap respon JSON harus berisi properti (misalnya {otentikasi: salah}) dan klien harus mengujinya setiap saat: jika salah, maka kontroler / layanan Angular akan "mengarahkan" ke halaman login.

Dan apa yang terjadi jika pengguna menangkap de JSON dan mengubah bool menjadi True?

Saya pikir Anda tidak boleh mengandalkan sisi klien untuk melakukan hal-hal semacam ini. Jika pengguna tidak diautentikasi, server sebaiknya mengarahkan ulang ke halaman login / kesalahan.

Doum
sumber
2
Periksa ini: github.com/witoldsz/angular-http-auth - interseptor memeriksa kode status respons server dan jika 403 ('diperlukan login') itu menyiarkan acara, sehingga Anda dapat menangkapnya di dalam aplikasi dan menampilkan kotak masuk.
aherok
10
Berhenti membalas satu sama lain menggunakan jawaban. Untuk itulah komentar tersebut!
Soviut
Saran @aherok, komentar Anda harus dipromosikan menjadi jawaban, itu akan dipilih ke atas pada waktunya. selebihnya hanya kebisingan.
pengguna237419
0

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

Nver Abgaryan
sumber