2015年9月4日 星期五

[AngularJS] 使用OWIN Identity的授權及認證

 AngularJS   OAuth   IDENTITY



背景


建立了後端的OWIN Identity Authentication ServerResource Server後,
( PS.請參考 Token Authentication with ASP.NET OWIN Identity (1) 的系列文章 )

本篇將以AngularJS來實作:
1.  登入以Authentication Server做認證並取得token
2.  token儲存於Session,供前端取得Resource Server的授權及取得資源。


環境


l   Bootstrap v3.3.4
l   AngularJS v1.4.4
l   HTML 5




實作



Factory : 提供Resource Server服務的URL

建立一webapiUrlFactory-controllers.js
提供一個webapiUrlFactory 以提供其他controller使用。

var app = angular.module('app').
factory('webapiUrlFactory', function () {
    var factory = {};

    //Web Api urls (Owin Authentication Server)
    factory.REGISTER_URL = "http://localhost:7531/api/Account/Register";
    factory.LOGIN_URL = "http://localhost:7531/token";
    factory.GET_ALL_USERS_URL = "http://localhost:7531/api/Account/GetAllUsers";
    factory.UNREGISTER_URL = "http://localhost:7531/api/Account/Unregister";

    //Web Api urls (Resource Server)
    factory.TEST_URL = "http://localhost:3241/api/Test/Get";

    return factory;
});


$rootScope : 提供共用參數

l   root-controller.js

有需要共用的參數可以丟在這裡~

var app = angular.module('app')
.run(function ($rootScope) {

    //定義佈署後的網站名稱 (如果有的話)
    $rootScope.WebSiteName = "";
});




Login

請利用Bootsnipp login template 找一個登入頁面`,或自行設計。
HTML裡面應至少包含input欄位,當然別忘了import所需要的.js

l   HTML

<div ng-app="app">
    <div ng-controller="LoginCtrl">
        <form ng-submit="login()">
            <fieldset>
                <input placeholder="Username" id="username" type="text"
ng-model="User.Id">
                <input placeholder="Password" id="password" type="password"
ng-model="User.Pwd">
                <br></br>
                <input type="submit" id="login" value="Login »">
            </fieldset>
        </form>
    </div>
</div>


接著建立LoginCtrl這個controller

l   login-controllers.js

var app = angular.module('app', [])
.controller('LoginCtrl', function ($scope, $rootScope, $http, webapiUrlFactory) {
    $scope.User = {"Id":"", "Pwd":""};

    $scope.login = function () {
        var postUrl = webapiUrlFactory.LOGIN_URL;
        var postData = "grant_type=password&username=" + $scope.User.Id + "&password=" + $scope.User.Pwd;

        $http({
            method: 'POST',
            url: postUrl,
            data: postData,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'} //bodyform data格式,必須指定Content-type
        }
        )
        .error(function (data, status, headers, config) {
            swal("Login failed", data, "error");
        }).success(function (data) {
            //Keep the token into session
            sessionStorage["token"] = data.access_token;

            swal("Login successfully!", "Welcome, " + $scope.User.Id, "success");
            //Wait and then Redirect
            var redirectUrl = window.location.origin + "/" + $rootScope.WebSiteName + "/Authentication/User";
            setTimeout(function () { location.href = redirectUrl; }, 2000);
           
        });
    }

}
);

重點如下~

1.  引用 Factory $rootScope

2.  注意在傳送認證資訊:”grant_type=password&username=JB&password=XXXX” 時, 必須以form data的格式送出,因此在這邊必須在 $http 指定 Header加入:

'Content-Type': 'application/x-www-form-urlencoded'

3.  Response data 將為
{"access_token":"…","token_type":"bearer","expires_in":172799}

我們將access_token儲存在session



到此已完成藉由輸入ID/PWD以取得token的登入頁面。









查詢Resource Server上的服務

User這個頁面,主要會做兩次Http Get Request 一次是從Authentication Server取得目前所有已認證的使用者ID : userList 另外一次則是到Resource Server取得一個測試的字串: bottomWords 放在頁面最下方。

l   HTML

<script src="~/Scripts/AngularJsController/user-controllers.js"></script>
<script src="~/Scripts/AngularJsController/webapiUrlFactory-controllers.js"></script>

<div ng-app="app">
    <div ng-controller="UserCtrl">
        <table data-toggle="table" class="table">
            <tr class="tr-class-1">
                <td>User Name</td>
            </tr>
            <tr class="tr-class-2" ng-repeat="item in userList">
                <td ng-class="UnregisterClass">{{item.UserName}}</td>
            </tr>
         </table>

        <div><center>{{bottomWords}}</center></div>
    </div>
</div>



l   user-controllers.js

var app = angular.module('app', [])
.controller('UserCtrl', function ($scope, $http, $location, webapiUrlFactory) {

    $scope.name = "";
    $scope.bottomWords = "";
    $scope.userList = [];

    /* Get all the users' information */
    $http({
        method: 'GET',
        url: webapiUrlFactory.GET_ALL_USERS_URL,
        headers:
            {
                'Authorization': 'bearer ' + sessionStorage['token']
            }
    }
        ).success(function (users) {
            $scope.userList = users;
        }).error(function (data, status, headers, config) {
            console.log(data, status, headers, config);
        });

    /* get the words showed in the bottom */
    $http({
        method: 'GET',
        url: webapiUrlFactory.TEST_URL,
        headers:
            { 'Authorization': 'bearer ' + sessionStorage['token'] }
    }).success(function (data) {
        $scope.bottomWords = data[0];
    });
});

u  因後端的Http Restful Service目前都需要授權才能使用,因此在每次Request加上Header

'Authorization': 'bearer ' + sessionStorage['token']











Reference












沒有留言:

張貼留言