標籤:
如今的app,利用各種前端架構結合html5的混合開發模式已然盛極一時。其中ionic+angularjs更是如日中天。這種模式利用angularjs $http 請求資料api 以達到前後端分離深得人心。說到webapi 跨域和認證授權始終是不得不提的。這種現成的例子有很多,但我發現的要麼是過於複雜,不利於第一次有效理解整個過程;要麼就是側重點比較單一,不好囊括;要麼就是其中有些坑沒有踩到,換個環境就一頭霧水。
所以,我打算以最簡單的實現方式最大限度地尋找其中的一些坑和注意點。
1.來看看我們的webapi代碼
首先我們實現自己的AuthorizeFilter
public class HttpBasicAuthorizeAttribute : AuthorizeAttribute { protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) { if (actionContext.Request.Method == HttpMethod.Options) return true; if (actionContext.Request.Headers.Authorization != null && actionContext.Request.Headers.Authorization.Parameter != null) { // System.Web.Security.FormsAuthentication. var userdata= System.Text.Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter)); if (userdata.Equals(String.Format("{0}:{1}", "tzy", "123"))) { return true; //base.IsAuthorized(actionContext); } } return false; // return base.IsAuthorized(actionContext); } protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext) { HttpResponseMessage hrm = new HttpResponseMessage(HttpStatusCode.Unauthorized); hrm.Headers.Add("WWW-Authenticate","Basic"); throw new HttpResponseException(hrm); } }
這些代碼值得注意的地方及說明
1. if (actionContext.Request.Method == HttpMethod.Options) 這個判斷是在進行跨域訪問時瀏覽器會發起一個Options請求去試探這個請求,但是他不會帶著data參數和一些header參數,所以認證肯定沒法通過導致無法繼續進行,所以給他直接認證通過。(對非跨域的則沒有影響)
2.對Authorization.Parameter 的解密,這裡的解析跟登陸成功之後返回的Token 加密方式相同就行 這裡採用的是Basic認證方式(簡單的64位字串)
3.HandleUnauthorizedRequest方法 這裡因為是繼承重寫的AuthorizeAttribute,在IsAuthorized 返回False的時候會執行這個方法
這裡是返回一個401的錯誤資訊
4.hrm.Headers.Add("WWW-Authenticate","Basic"); 這段代碼我們後面再說一下
2.然後定義我們的apiController
[HttpBasicAuthorize] public class BasicController : ApiController {
[HttpGet] public IEnumerable<string> Get() { return new string[] { "tzy","123"}; }}
然後我習慣更改一下api的路由 就改了一下routeTemplate 加入/{action}
public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); // config.Filters.Add(new AuthorizeAttribute()); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); }
webapi裡面有xml 和json 兩種
反正我比較喜歡json
這是一種方式,當然還有其他的方式來更改formatter 這裡就不深究了
protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); }
3.我們來看一下效果吧
通過瀏覽器訪問 第一次認證沒有成功 然後就會執行我們上面說的那個 HandleUnauthorizedRequest 方法
之前說到的 hrm.Headers.Add("WWW-Authenticate","Basic"); 這句代碼指示瀏覽器 認證方式為Basic 然後瀏覽器自動彈出一個登陸視窗並以basic 的方式 加密後每次通過header 傳輸到伺服器進行認證然後得到授權
到這裡呢,我們對 整個webapi的授權認證有了一個比較直觀的認識,下一篇將繼續結合這個例子。在跨域的環境下通過ajax(angularjs $http)來完成這個過程。
angularjs+webapi2 跨域Basic 認證授權(一)