HTTP Basic Authentication AngularJS
Bài đăng này đã không được cập nhật trong 7 năm
Bài viết này là một ví dụ về trang login với HTTP Basic Authentication
sử dụng AngularJS và nó sẽ lưu trạng thái đăng nhập của người dùng sau khi refresh trang.
Prerequisite
- BrowserSync là một npm package nó cần cài đặt trước Node.js trước. Để install BrowserSync mở terminal và gõ:
npm install -g browser-sync
. - Bower để quản lý các framworks, libraries, assets và utilities.
npm install -g bower
Nếu lúc cài đặt bị lỗi permission hãy thêm "sudo" trước câu lệnh cài đặt.
Setup
Tạo một thư mục project
mkdir angularjs-basic-http-authentication && cd angularjs-basic-http-authentication
Tải các thư viện để áp dụng vào project
bower init
(điền các thông tin cần thiết)bower install bootstrap --save
bower install angular --save
bower install angular-route --save
bower install angular-cookies --save
angularjs-basic-http-authentication
- index.html
/angular
/scripts
- app.js
- authentication_service.js
- home_controller.js
- login_controller.js
/views
- home.html
- login.html
/images
- loading.gif
/bower_components
Coding
Theo cấu trúc ở trên thì bắt đầu viết code cho từng file một.
index.html
/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS Basic HTTP Authentication</title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css" />
<script src="bower_components/jquery/dist/jquery.slim.min.js"></script>
<script src="bower_components/tether/dist/js/tether.min.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="angular/scripts/app.js"></script>
<script src="angular/scripts/authentication_service.js"></script>
<script src="angular/scripts/login_controller.js"></script>
<script src="angular/scripts/home_controller.js"></script>
</head>
<body ng-app="BasicHttpAuthApp">
<div class="jumbotron">
<div class="container">
<div class="col-xs-offset-2 col-xs-8">
<div ng-view></div>
</div>
</div>
</div>
</body>
</html>
Home view
hiển thị text báo đến user đã đăng nhập thành công.
/angular/views/home.html
<h1>Home</h1>
<p>You're logged in!!</p>
<p><a href="#!/login">Logout</a></a></p>
Login view
gồm các form login với các inputs và các validation messages.
/angular/views/login.html
<div ng-show="error" class="alert alert-danger">{{error}}</div>
<form name="form" ng-submit="login()" role="form">
<div class="form-group">
<label for="username">Username</label>
<i class="fa fa-key"></i>
<input type="text" name="username" id="username" class="form-control" ng-model="username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<i class="fa fa-lock"></i>
<input type="password" name="password" id="password" class="form-control" ng-model="password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
</div>
<div class="form-actions">
<button type="submit" ng-disabled="form.$invalid || dataLoading" class="btn btn-danger">Login</button>
<img ng-if="dataLoading" src="images/loading.gif"/>
</div>
</form>
AngularJS App
file app.js là root cửa ứng dụng AngularJS, xác định tên app, các dependencies, routes và cầu hình startup. Phương thức
run()
ở đây để khởi tạo biến currentUser từ một cookie để giữ người dùng đã đăng nhập khi reload trang, nó cũng chứa các event handler để kiểm tra xem người dùng đã đăng nhập hay chưa trước khi route thay đổi.
/scripts/app.js
"use strict";
var module_authen = angular.module("Authentication", []);
var module_home = angular.module("Home", []);
var basicHttpAuthApp = angular.module("BasicHttpAuthApp", ["Authentication", "Home", "ngRoute", "ngCookies"]);
basicHttpAuthApp.config(["$routeProvider", function ($routeProvider) {
$routeProvider
.when("/login", {
controller: "LoginController",
templateUrl: "angular/views/login.html"
})
.when("/", {
controller: "HomeController",
templateUrl: "angular/views/home.html"
})
.otherwise({ redirectTo: "/login" });
}])
basicHttpAuthApp.run(["$rootScope", "$location", "$cookieStore", "$http",
function ($rootScope, $location, $cookieStore, $http) {
$rootScope.globals = $cookieStore.get("globals") || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common["Authorization"] = "Basic " + $rootScope.globals.currentUser.authdata; // jshint ignore:line
}
$rootScope.$on("$locationChangeStart", function (event, next, current) {
if ($location.path() !== "/login" && !$rootScope.globals.currentUser) {
$location.path("/login");
}
});
}
]);
Login Controller
chứa phương thức
login()
sử dụng Authentication Service để validate username và password nhập trong màn hình login.
/scripts/login_controller.js
"use strict";
module_authen.controller("LoginController", ["$scope", "$rootScope", "$location", "AuthenticationService",
function ($scope, $rootScope, $location, AuthenticationService) {
AuthenticationService.ClearCredentials();
$scope.login = function () {
$scope.dataLoading = true;
AuthenticationService.Login($scope.username, $scope.password, function(response) {
if(response.success) {
AuthenticationService.SetCredentials($scope.username, $scope.password);
$location.path("/");
} else {
$scope.error = response.message;
$scope.dataLoading = false;
}
});
};
}]);
Home Controller
phần này chỉ hiển thị text nên chưa có logic để xử lý
/scripts/home_controller.js
"use strict";
module_home.controller("HomeController", ["$scope", function ($scope) {
}]);
Authentication Service
đóng vài trò là interface giữa angularjs app và server side api, vậy các http requests sẽ quản lý ở đây. Nó chứa một service Base64 để mã hóa username và password để dùng cho HTTP Authorization header cho tất cả request sau khi đăng nhập.
/scripts/authentication_service.js
"use strict";
module_authen.factory("AuthenticationService",
["Base64", "$http", "$cookieStore", "$rootScope", "$timeout",
function (Base64, $http, $cookieStore, $rootScope, $timeout) {
var service = {};
service.Login = function (username, password, callback) {
$timeout(function(){
var response = { success: username === "framgia" && password === "test123" };
if(!response.success) {
response.message = "Username or password is incorrect";
}
callback(response);
}, 1000);
};
service.SetCredentials = function (username, password) {
var authdata = Base64.encode(username + ":" + password);
$rootScope.globals = {
currentUser: { username: username, authdata: authdata }
};
$http.defaults.headers.common["Authorization"] = "Basic " + authdata;
$cookieStore.put("globals", $rootScope.globals);
};
service.ClearCredentials = function () {
$rootScope.globals = {};
$cookieStore.remove("globals");
$http.defaults.headers.common.Authorization = "Basic ";
};
return service;
}]);
module_authen.factory("Base64", function () {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return {
encode: function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) +
keyStr.charAt(enc2) +
keyStr.charAt(enc3) +
keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
},
decode: function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
window.alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, "+", "/",and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}
};
});
Demo
Để chạy server gõ command browser-sync start --server --files "*.html"
trong thư mục của project.
References
All rights reserved