ASP.NET MVC5+EF6+EasyUI 後台管理系統(65)-MVC WebApi 使用者驗證 (1)

來源:互聯網
上載者:User

標籤:get   www   height   soft   password   2-2   備忘   邏輯   設定   

系列目錄前言:

WebAPI主要開放資料給手機APP,其他需要得知資料的系統,或者軟體應用,所以移動端與系統的資料來源往往是相通的。

Web 使用者的身分識別驗證,及頁面操作許可權驗證是B/S系統的基礎功能,一個功能複雜的業務應用系統,通過角色授權來控制使用者訪問

本文通過Basic 方式進行基礎認證Mvc的Controller基類及Action的許可權驗證來實現Web系統登入,Mvc前端許可權校正以及WebApi服務端的訪問校正功能,本文主要作為本人備忘使用,如能給予人協助,深感榮幸,歡迎討論和指正,下面梳理一下驗證的流程

開發環境:

VS2015+無資料庫(類比資料)

知識點:
  1. WebApi簡單使用
  2. 使用者校正
  3. 同域訪問
  4. 跨域訪問
驗證流程:

1.WebApi服務端接收訪問請求,需要做安全驗證處理,驗證處理步驟具體如下:

1) 如果是合法的Http請求,在Http要求標頭中會有使用者身份的票據資訊(如果是跨域那麼無法在要求標頭中添加票據),服務端會讀取票據資訊,並校正票據資訊是否完整有效,如果滿足校正要求,則進行業務資料的處理,並返回給請求發起方;

2) 如果沒有票據資訊,或者票據資訊不是合法的,則返回“未授權的訪問”異常訊息給前端,由前端處理此異常。

2. 登入及許可權驗證流程

1) 使用者開啟瀏覽器,並在地址欄中輸入頁面請求地址,提交;

2) 瀏覽器解析Http請求,發送到Web伺服器;Web伺服器驗證使用者請求,首先判斷是否有登入的票據資訊;

3) 使用者沒有登入票據資訊,則跳轉到登入頁面;

4) 使用者輸入使用者名稱和密碼資訊;

5) 瀏覽器提交登入表單資料給Web伺服器;

6) Web服務需要驗證使用者名稱和密碼是否匹配,發送api請求給api伺服器;

7) api使用者賬戶服務根據使用者名稱,讀取儲存在資料庫中的使用者資料,判斷密碼是否匹配;

7.1)如果使用者名稱和密碼不匹配,則提示密碼錯誤等資訊,然該使用者重新填寫登入資料;

7.2)如果驗證通過,則儲存使用者票據資訊;

8)

3.如果使用者有登入票據資訊,則跳轉到使用者請求的頁面;

9) 驗證使用者對當前要操作的頁面或頁面元素是否有許可權操作,首先需要發起api服務要求,擷取使用者的許可權資料;

10). api使用者權限服務根據使用者名稱,尋找該使用者的角色資訊,並計算使用者權限列表,封裝為Json資料並返回;

11). 當使用者有許可權操作頁面或頁面元素時,跳轉到頁面,並由頁面Controller提交業務資料處理請求到api伺服器; 如果使用者沒有許可權訪問該頁面或頁面元素時,則顯示“未授權的訪問操作”,跳轉到系統異常處理頁面。

12). api商務服務處理商務邏輯,並將結果以Json 資料返回;

13). 返回渲染後的頁面給瀏覽器前端,並呈現業務資料到頁面;

14). 使用者填寫業務資料,或者尋找業務資料;

15). 當填寫或尋找完業務資料後,使用者提交表單資料;

16). 瀏覽器指令碼提交get,post等請求給web伺服器,由web伺服器再次解析請求操作,重複步驟2的後續流程;

17). 當api伺服器驗證使用者身份是,沒有可信使用者票據,系統提示“未授權的訪問操作”,跳轉到系統異常處理頁面。

開始:1.添加一個空的WebApi,無身分識別驗證WebApi

2.建立Account控制器 AccountController
using Apps.Common;using Apps.WebApi.Models;using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web;using System.Web.Http;using System.Web.Security;namespace Apps.WebApi.Controllers{    public class AccountController : ApiController    {        [HttpGet]        public object Login(string userName, string password)        {            //實際情境應該到資料庫進行校正            if (userName != "123" && password!="123")            {                return Json(JsonHandler.CreateMessage(0, "使用者名稱或密碼錯誤"));            }            FormsAuthenticationTicket token = new FormsAuthenticationTicket(0, userName, DateTime.Now,                            DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", userName, password),                            FormsAuthentication.FormsCookiePath);            //返回登入結果、使用者資訊、使用者驗證票據資訊            var Token = FormsAuthentication.Encrypt(token);            //將身份資訊儲存在session中,驗證當前請求是否是有效請求            HttpContext.Current.Session[userName] = Token;            return Json(JsonHandler.CreateMessage(1, Token));        }    }}

對使用者名稱和密碼進行校正,這裡沒有資料庫示範,所以直接是進行固定匹配,帳號123,密碼123(可參考19節使用者登入,獲得資料庫的校正方式)

登入失敗:返回錯誤提示

登入成功:返回Token並儲存Token到 Session

可見代碼中包含Session的操作,但是Webapi預設是不支援Session的,所以我們需要在Global載入時候添加對Session的支援,不然運行調用會直接異常

    protected void Application_PostAuthorizeRequest()    {        HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);    }
3.運行Webapi

輸入http://localhost:13743/help可以看到,我們的介面已經在webapi help列出,並可以查看調用方式(VS2012可能沒有自動產生WebApi Help,需要從Nuget包獲得)

4.同域調用

在Home的Index.cshtm添加登入代碼

<script src="~/Scripts/jquery-1.10.2.min.js"></script><style>html,body{height:100%}.box{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=‘#6699FF‘, endColorstr=‘#6699FF‘);background-image:linear-gradient(bottom,#69F 0,#69F 100%);background-image:-o-linear-gradient(bottom,#69F 0,#69F 100%);background-image:-moz-linear-gradient(bottom,#69F 0,#69F 100%);background-image:-webkit-linear-gradient(bottom,#69F 0,#69F 100%);background-image:-ms-linear-gradient(bottom,#69F 0,#69F 100%);margin:0 auto;position:relative;width:100%;height:100%}.login-box{width:100%;max-width:500px;height:400px;position:absolute;top:50%;margin-top:-200px}@@media screen and (min-width:500px){.login-box{left:50%;margin-left:-250px}}.form{width:100%;max-width:500px;height:275px;margin:25px auto 0 auto;padding-top:25px}.login-content{height:300px;width:100%;max-width:500px;background-color:rgba(255,250,2550,.6);float:left}.input-group{margin:0 0 30px 0!important}.form-control,.input-group{height:40px}.form-group{margin-bottom:0!important}.login-title{padding:20px 10px;background-color:rgba(0,0,0,.6)}.login-title h1{margin-top:10px!important}.login-title small{color:#fff}.link p{line-height:20px;margin-top:30px}.btn-sm{padding:8px 24px!important;font-size:16px!important}</style><div class="box" style="margin:100px;height:400px;width:500px;">    <div class="login-box">        <div class="login-title text-center">            <h1><small>登入</small></h1>        </div>        <div class="login-content ">            <div class="form">                <form action="#" method="post">                    <div class="form-group">                        <div class="col-xs-12  ">                            <div class="input-group">                                <span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>                                <input type="text" id="username" name="username" class="form-control" placeholder="使用者名稱">                            </div>                        </div>                    </div>                    <div class="form-group">                        <div class="col-xs-12  ">                            <div class="input-group">                                <span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span>                                <input type="text" id="password" name="password" class="form-control" placeholder="密碼">                            </div>                        </div>                    </div>                    <div class="form-group form-actions">                        <div class="col-xs-4 col-xs-offset-4 ">                            <button type="button" id="Login" class="btn btn-sm btn-info"><span class="glyphicon glyphicon-off"></span> 登入</button>                        </div>                    </div>                                </form>            </div>        </div>    </div></div><script>    $(function () {        $("#Login").click(function () {            $.ajax({                type: "get",                url: "/api/Account/Login",                data: { userName: $("#username").val(), password: $("#password").val() },                success: function (data, status) {                        if (data.type==0) {                            alert("登入失敗");                            return;                        }                        alert("登入成功:Token"+data.message);                },                error: function (e) {                    alert("登入失敗!");                },                complete: function () {                }            });        });    });</script>

瀏覽器中運行/Home/Index

 

成功取得Token

5.跨域訪問

同網域名稱訪問,一般系統任務這是安全的,可以信任的,所以不需要做過多的考慮,這是我們來看看跨域的情況

1.便於好記,把Apps.WebApi的連接埠設定為固定的8866

2.建立一個新的Web MVC普通無使用者驗證網站Apps.Web 設定連接埠為4455

把8866的Home/index登入介面代碼複製到4455下的Home/index,修改訪問URL

 url: "http://localhost:8866/api/Account/Login"

3.設定解決方案為多項目啟動,同時啟動4455,8866

這樣才用讓4455去訪問6655的API,不然絕對報404

訪問成功,但是沒有傳回值,jquery顯示jquery的jsonp格式有callback返回

設定Ajax的dataType 為Jsonp

dataType:"jsonp",

再次運行,帶回來的值正常

但是結果並沒有彈出token並提示一個js錯誤

到這裡真是一波三折

因為返回的值是:{"Id":"123"}

然而Jsonp需要你返回:jQuery*([{"Id":123"}])

4.讓WebApi支援跨域返回的格式

註冊一個全域屬性

using System.Net.Http;using System.Text;using System.Web;using System.Web.Http.Filters;namespace Apps.WebApi.Core{    public class JsonCallbackAttribute : ActionFilterAttribute    {        private const string CallbackQueryParameter = "callback";        public override void OnActionExecuted(HttpActionExecutedContext context)        {            var callback = string.Empty;            if (IsJsonp(out callback))            {                var jsonBuilder = new StringBuilder(callback);                jsonBuilder.AppendFormat("({0})", context.Response.Content.ReadAsStringAsync().Result);                context.Response.Content = new StringContent(jsonBuilder.ToString());            }            base.OnActionExecuted(context);        }        private bool IsJsonp(out string callback)        {            callback = HttpContext.Current.Request.QueryString[CallbackQueryParameter];            return !string.IsNullOrEmpty(callback);        }    }}
GlobalConfiguration.Configuration.Filters.Add(new JsonCallbackAttribute());

再次運行:

本節結束,下節再學習怎麼利用Token進行訪問獲得許可權

參考資料:

http://stackoverflow.com/questions/9594229/accessing-session-using-asp-net-web-api

http://stackoverflow.com/questions/23698804/asp-net-mvc-with-forms-auth-and-webapi-with-basic-auth

https://weblog.west-wind.com/posts/2013/apr/18/a-webapi-basic-authentication-authorization-filter

http://stackoverflow.com/questions/17121964/asp-net-web-api-restful-web-service-basic-authentication

http://www.cnblogs.com/Kummy/p/3767269.html

執行個體代碼下載   訪問密碼 13df

 

ASP.NET MVC5+EF6+EasyUI 後台管理系統(65)-MVC WebApi 使用者驗證 (1)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.