Ø  前言

在 Web 项目中授权认证方式有很多种,本文主要讲述基于 Basic 的认证方式。这是一种比较简单、常见的认证方式,主要是将请求的用户名和密码进行加密后返回给调用方,比较适合采用用户名、密码授权的项目中,比如:网站系统、后台管理系统、以及前后端分离的 APP 应用等。

1.   首先,来看一下基于 Basic 认证的请求模式

2.   具体实现步骤

1)   首先,新建一个授权过滤器(RequestAuthorizeAttribute),可以继承于 System.Web.Http.AuthorizationFilterAttribute,或者 System.Web.Http.AuthorizeAttribute,因为 AuthorizeAttribute 也是 AuthorizationFilterAttribute 的派生类。

/// <summary>

/// 请求授权特性。

/// </summary>

public class RequestAuthorizeAttribute : System.Web.Http.AuthorizeAttribute

{

public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)

{

//首先检查 Action 或 Controller 是否允许匿名访问

if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0

|| actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)

{

base.OnAuthorization(actionContext);

}

else

{   //不允许匿名访问

var authorization = actionContext.Request.Headers.Authorization;

if (authorization != null)

{

if ("Basic".Equals(authorization.Scheme, StringComparison.CurrentCultureIgnoreCase)

&& !string.IsNullOrEmpty(authorization.Parameter))

{

try

{

var ticket = System.Web.Security.FormsAuthentication.Decrypt(authorization.Parameter);

string[] array = ticket.UserData.Split('&');    //获取加密前的用户数据(用户名和密码)

//登录时:已经验证了用户名和密码,所以这里只需要验证票据是否过期

if (ticket.Expired)

{

//也可以使用 actionContext.ControllerContext.Request,与 actionContext.Request 是同一实例。

actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(

System.Net.HttpStatusCode.BadRequest, "身份票据已过期");

}

else

{

base.IsAuthorized(actionContext);

}

}

catch (Exception ex)

{

actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(

System.Net.HttpStatusCode.Unauthorized, string.Format("授权鉴定异常,{0}", ex.Message));

}

}

else { HandleUnauthorizedRequest(actionContext); }

}

else { HandleUnauthorizedRequest(actionContext); }

}

}

}

1.   在授权过滤器中,首先检查当前 Action 或 Controller 是否允许匿名访问。如果允许则跳过授权验证,否则需要验证传递的票据以及是否过期。

2)   新建一个控制器(用于验证登录用户名和密码)

/// <summary>

/// 账户控制器。

/// </summary>

[RequestAuthorize]

[RoutePrefix("api/account")]

public class AccountController : ApiController

{

/// <summary>

/// 登录。

/// </summary>

[Route("login"), HttpPost]

[AllowAnonymous]

public object Login(Newtonsoft.Json.Linq.JObject jObj)

{

//两种方式获取 JObject 中的值

string userName = jObj.GetValue("UserName").ToObject<string>();

Newtonsoft.Json.Linq.JToken token = null;

string password = null;

if (jObj.TryGetValue("Password", out token))

password = token.ToObject<string>();

else

throw new System.ArgumentException("获取密码失败");   //异常将被异常过滤器捕获

//模拟用户数据(应该是从数据库获取)

var userData = new

{

UserId = 1,

UserName = "aibaincheng",

Password = "abc123" //可以将密码加密后保存至数据库(以提高安全性)

};

if (userData.UserName == userData.UserName && userData.Password != password)

return new { Msg = "用户名或密码错误" };

else

{

//以 Forms 身份验证加密

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(

1,

userName,

DateTime.Now,

DateTime.Now.AddMinutes(3), //票据3分钟后失效

true,

string.Format("{0}&{1}", userName, password),

FormsAuthentication.FormsCookiePath);

string ticketStr = FormsAuthentication.Encrypt(ticket);

return new { UserId = userData.UserId, Expire = DateTime.Now.AddMinutes(3), Ticket = ticketStr };

}

}

}

1.   在控制器上加了 RequestAuthorize 特性,并在 Login Action 上也加了 AllowAnonymous 特性,这样最终还是以 Action 的为准,表示该 Action 可以匿名访问(跳过了授权验证)。

2.   拿到请求的用户名和密码,与数据库中的用户名密码进行匹配。如果匹配成功则生成加密的票据返回,否则返回错误信息。

3)   再新建另一个控制器(用于授权测试)

/// <summary>

/// 客户控制器。

/// </summary>

[RequestAuthorize]

[RoutePrefix("api/customer")]

public class CustomerController : ApiController

{

[Route("get"), HttpGet]

public object Get(int id)

{

//这里完成查询客户的操作...

return new { Code = 200, Data = new { CustomerId = id, CustomerName = "客户A", Address = "上海市杨浦区" } };

}

}

1.   同样在控制器上加了 RequestAuthorize 特性,表示控制器中的所有 Action 方法都将采用 RequestAuthorize 过滤器完成授权验证。

2.   因为该接口需要授权访问,所以在调用该接口时,必须将 Ticket(票据)传递给服务器端,否则不能访问该接口。

3.   模拟客户端调用

1)   Account/Login 调用失败

2)   Account/Login 调用成功

3)   Customer/Get 调用失败(票据过期)

4)   Customer/Get 调用失败(无票据)

5)   Customer/Get 调用失败(错误的票据)

6)   Customer/Get 调用成功

Ø  总结

1)   关于 Basic 认证的方式,服务端可能存在不同的处理方式,比如:有将请求用户名+密码进行 base64 编码的方式,也有将票据 MD5 加密等。

2)   但无论使用哪种方式,都是将票据经过不同的处理后传递给调用方,调用方再请求其他需授权的接口时,在将票据“带过来”,完成身份认证。

3)   最后简单分析下 Basic 认证的优缺点:

1.   优点

1)   简单,无论是调用方还是服务端实现起来都比较简单。

2.   缺点

1)   存在安全隐患,因为会比较频繁的向服务端提供用户名和密码来换取票据,容易被其他程序截取或破解。比较适合一些内部系统,或者安全要求比较低的项目。

2)   只适合以用户名+密码的访问方式,所有的调用者首先必须有用户名、密码,这样就说明只能是在同一套系统或框架中使用。

4)   好了 Basic 认证就先讨论到这里,如有不对之处,欢迎指正,感激不尽,嘿嘿~~

ASP.NET Web API 2 使用 AuthorizationFilter(授权过滤器)实现 Basic 认证的更多相关文章

  1. ASP.NET Web API身份验证和授权

    英语原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-a ...

  2. Web Api 过滤器之 AuthorizationFilter 验证过滤器

    该过滤器是最先执行的过滤器,即使把它放在最后 API [MyActionFilter] [MyExceptionFilter] [MyAuthorize] public void Get() { Tr ...

  3. ASP.NET Web API 安全验证之摘要(Digest)认证

    在基本认证的方式中,主要的安全问题来自于用户信息的明文传输,而在摘要认证中,主要通过一些手段避免了此问题,大大增加了安全性. 1.客户端匿名的方式请求 (无认证) HTTP/ Unauthorized ...

  4. ASP.NET Web API 2 使用 DelegatingHandler(委托处理程序)实现签名认证

    Ø  前言 在前一篇ASP.NET Web API 2 使用 AuthorizationFilter(授权过滤器)实现 Basic 认证文章中实现了采用 Basic 认证的方式,但是这种方式存在安全隐 ...

  5. ASP.NET Web API 2 过滤器

    Ø  前言 我们知道 ASP.NET Web API 过滤器,也是属于消息处理机制中的一部分.正因如此,我们经常使用它来完成对请求的授权验证.参数验证,以及请求的 Log 记录,程序异常捕获等. 1. ...

  6. 用Middleware给ASP.NET Core Web API添加自己的授权验证

    Web API,是一个能让前后端分离.解放前后端生产力的好东西.不过大部分公司应该都没能做到完全的前后端分离.API的实现方式有很 多,可以用ASP.NET Core.也可以用ASP.NET Web ...

  7. [转]用Middleware给ASP.NET Core Web API添加自己的授权验证

    本文转自:http://www.cnblogs.com/catcher1994/p/6021046.html Web API,是一个能让前后端分离.解放前后端生产力的好东西.不过大部分公司应该都没能做 ...

  8. ASP.NET Web API自身对CORS的支持: CORS授权检验的实施

    通过<EnableCorsAttribute特性背后的故事>我们知道:由CorsPolicyProvider提供的CorsPolicy表示目标Action采用的资源授权策略,ASP.NET ...

  9. 新作《ASP.NET Web API 2框架揭秘》正式出版

    我觉得大部分人都是“眼球动物“,他们关注的往往都是目光所及的东西.对于很多软件从业者来说,他们对看得见(具有UI界面)的应用抱有极大的热忱,但是对背后支撑整个应用的服务却显得较为冷漠.如果我们将整个“ ...

随机推荐

  1. 覆盖的面积 HDU - 1255 (扫描线, 面积交)

    求n个矩阵面积相交的部分,和求面积并一样,不过这里需要开两个数组保存覆盖一次和覆盖两次以上的次数的部分,还是模板,主要注意点就是pushup部分,如果我已经被两次覆盖,那我的两个数组在这个root点的 ...

  2. request.getRequestDispatcher 页面跳转,样式丢失。

    在页面中引用样式和其它资源的时候,尽量不要用相对路径,因为"当前路径"这个概念在J2EE中是不稳定的. 所以最好都是绝对路径,类似于: <% String cp = requ ...

  3. (七)修改上一条SQL语句,NULL值的滤空函数nvl

    修改上一条SQL语句 1.用c命令来修改(c 即 change ) 默认,光标闪烁位置指向上一条SQL语句的第一行.输入二则定位到第二行. c /错误的关键字/正确的关键字 SQL form emp; ...

  4. 手机nv

    NV值是记录手机的射频参数的,和手机的IMEI号.手机信号.WIFI信号等有关,如果NV值刷没了,手机没有这些校准的数据了,会对手机有一定的影响. qcn里面包含手机的imei 所有改变imei就改变 ...

  5. 解决access 导出 excel 字段截断错误的问题

    解决方法:这个问题通过从EXCEL中导入外部数据,也就是ACCESS数据可以解决. 1.选择导入数据 2.点击选择数据源 选择需要导入的access数据源

  6. 最短路经算法简介(Dijkstra算法,A*算法,D*算法)

    据 Drew 所知最短路经算法现在重要的应用有计算机网络路由算法,机器人探路,交通路线导航,人工智能,游戏设计等等.美国火星探测器核心的寻路算法就是采用的D*(D Star)算法. 最短路经计算分静态 ...

  7. php处理文件上传

    注意点: 1.<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" ...

  8. Python之字符编码与文件操作

    目录 字符编码 Python2和Python3中字符串类型的差别 文件操作 文件操作的方式 文件内光标的移动 文件修改 字符编码 什么是字符编码? ''' 字符编码就是制定的一个将人类的语言的字符与二 ...

  9. smarty实例

    login.php代码 <?phpinclude("../init.inc.php"); $smarty->display("login.html" ...

  10. Mysql数据约束 整理

    数据约束 1.默认值: 作用: 当用户对使用默认值的字段不插入值的时候,就使用默认值. 注意: 1)对默认值字段插入null是可以的. 2)对默认值字段可以插入非null   CREATE TABLE ...