ASP.NET Web API 实现客户端Basic(基本)认证 之简单实现
2016-05-25 07:55
691 查看
优点是逻辑简单明了、设置简单。
缺点显而易见,即使是BASE64后也是可见的明文,很容易被破解、非法利用,使用HTTPS是一个解决方案。
还有就是HTTP是无状态的,同一客户端每次都需要验证。
实现:
客户端在用户输入用户名及密码后,将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中,如当用户名为Parry,密码为123456时,客户端将用户名和密码用":"合并,并将合并后的字符串用BASE64加密,并于每次请求数据时,将密文附加于请求头(Request Header)中。
HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。
自定义属性HTTPBasicAuthorize ,继承AuthorizeAttribute,并实现两个方法:OnAuthorization和HandleUnauthorizedRequest。
这些代码值得注意的地方及说明
1. if (actionContext.Request.Method == HttpMethod.Options) 这个判断是在进行跨域访问时浏览器会发起一个Options请求去试探这个请求,但是他不会带着data参数和一些header参数,所以认证肯定没法通过导致无法继续进行,所以给他直接认证通过。(对非跨域的则没有影响)
2.对Authorization.Parameter 的解密,这里的解析跟登陆成功之后返回的Token 加密方式相同就行 这里采用的是Basic认证方式(简单的64位字符串)
3.HandleUnauthorizedRequest方法 这里因为是继承重写的AuthorizeAttribute,在IsAuthorized 返回False的时候会执行这个方法
这里是返回一个401的错误信息
4.challengeMessage.Headers.Add("WWW-Authenticate","Basic"); 这句代码指示浏览器 认证方式为Basic 然后浏览器自动弹出一个登陆窗口并以basic 的方式 加密后每次通过header 传输到服务器进行认证然后得到授权
在需要验证的Controller的类加上[HTTPBasicAuthorize]属性,即可对当前控制器下的所有方法实现基本身份认证
然后我习惯更改一下api的路由 就改了一下routeTemplate 加入/{action}
如果以webapi里面有xml 方式返回,更改formatter 如下
缺点显而易见,即使是BASE64后也是可见的明文,很容易被破解、非法利用,使用HTTPS是一个解决方案。
还有就是HTTP是无状态的,同一客户端每次都需要验证。
实现:
客户端在用户输入用户名及密码后,将用户名及密码以BASE64加密,加密后的密文将附加于请求信息中,如当用户名为Parry,密码为123456时,客户端将用户名和密码用":"合并,并将合并后的字符串用BASE64加密,并于每次请求数据时,将密文附加于请求头(Request Header)中。
HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证,如果用户名及密码正确,则根据客户端请求,返回客户端所需要的数据;否则,返回错误代码或重新要求客户端提供用户名及密码。
自定义属性HTTPBasicAuthorize ,继承AuthorizeAttribute,并实现两个方法:OnAuthorization和HandleUnauthorizedRequest。
public class HTTPBasicAuthorizeAttribute : System.Web.Http.AuthorizeAttribute { public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) { if (actionContext.Request.Headers.Authorization != null) { //对客户端进行BASE64后的字符串再解码 string userInfo = Encoding.Default.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter)); //用户验证逻辑 if (string.Equals(userInfo, string.Format("{0}:{1}", "Parry", "123456"))) { IsAuthorized(actionContext); } else { HandleUnauthorizedRequest(actionContext); } } else { HandleUnauthorizedRequest(actionContext); } } //或不重写OnAuthorization,对IsAuthorized方法重写 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) { var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized); challengeMessage.Headers.Add("WWW-Authenticate", "Basic"); throw new System.Web.Http.HttpResponseException(challengeMessage); } }
这些代码值得注意的地方及说明
1. if (actionContext.Request.Method == HttpMethod.Options) 这个判断是在进行跨域访问时浏览器会发起一个Options请求去试探这个请求,但是他不会带着data参数和一些header参数,所以认证肯定没法通过导致无法继续进行,所以给他直接认证通过。(对非跨域的则没有影响)
2.对Authorization.Parameter 的解密,这里的解析跟登陆成功之后返回的Token 加密方式相同就行 这里采用的是Basic认证方式(简单的64位字符串)
3.HandleUnauthorizedRequest方法 这里因为是继承重写的AuthorizeAttribute,在IsAuthorized 返回False的时候会执行这个方法
这里是返回一个401的错误信息
4.challengeMessage.Headers.Add("WWW-Authenticate","Basic"); 这句代码指示浏览器 认证方式为Basic 然后浏览器自动弹出一个登陆窗口并以basic 的方式 加密后每次通过header 传输到服务器进行认证然后得到授权
在需要验证的Controller的类加上[HTTPBasicAuthorize]属性,即可对当前控制器下的所有方法实现基本身份认证
然后我习惯更改一下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 方式返回,更改formatter 如下
protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); }
相关文章推荐
- asp.net 有关时间各种(输出)处理
- asp.net 文件 操作方法
- raspberry pi wifi
- ASP.NET动态创建树
- Microsoft.AspNet.Identity.EntityFramework 源码
- MVC 问题集锦
- ASP.NET MVC 阻止当前请求的视图页面缓存OutputCache
- [ASP.NET MVC]: - EF框架学习手记
- ASP.NET MVC中默认Model Binder绑定Action参数为List、Dictionary等集合的实例
- @Aspect注解无效
- ModeScaleToFill、ModeScaleAspectFit、ModeScaleAspectFill
- ASP.NET 模糊查询参数化
- Aspose WorkSheet 自动适应行高
- OWASP十大热门威胁及其对应工具
- AspNet WebApi : MessageHandler(消息处理器 )
- asp.net mvc4 webapi request获取参数
- ASP.NET MVC学习系列(二)-WebAPI请求
- ASP.NET——内置对象
- ASP.NET——初步了解
- Asp.Net Core子应用由于配置中重复添加模块会引起IIS错误500.19