ASP.NET MVC构建RESTful服务时返回Unauthorized(401)状态
2011-03-31 23:09
351 查看
这两天在构建RESTful服务的客户端,本以为已经一马平川了,没有想到就在下班时遇到一个问题。
我打算在服务器商把所处理的HTTP异常状态(400-599))状态一一返回给客户端组件,客户端收到各个状态码后根据号码及从服务器端返回的Description Content来抛出客户端的异常,结果在测试401时发现一个问题:在我的设想中,收到401,然后再去读取Response中的Status Description(我使用了自定义格式,详见上篇博文),结果出乎意料的是,服务器端发出了401,结果客户端没有抛出异常,而且按照接收成功的状态去了读取ATOM Feed的代码,而解析ATOM Feed时报错了,这让我很是诧异,经查看HttpStatusCode发现,返回的居然是200! RESTful的好处就是可以通过浏览器调用服务,把Url贴到浏览器中一看,原来返回的居然是LogOn视图...心中大概有数了,敢情MVC这家伙自做聪明,直接把401交给了Authentication Module去执行Unauthorized Handler了,整个过程类似在使用Authorize特性时用户没有登录一样(因为实际上在执行Authorization Filter时,也是通过HttpUnauthorizedResult实例将Response的StatusCode设置为401)。可是我现在使用的是客户端调用Web Service,你给我一个登录界面有啥用呢?再说了,我只是没有权限访问某个服务方法(Action),又不是没有登录,难道让我使用403去代替401么?但这不是我想要的,经过一番查找,发现在HttpApplication.EndRequest事件貌似可以,MSDN描述如下:“在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生”,最后一个事件应该是过了Authentication Module了吧,但是总觉得把这么一个事情放在Application中去处理,似乎有点太“重”了,凭什么其他的错误代码都可以作为ActionResult来处理,而一个401就能那么特殊呢,再说了,老衲一向痛恨“权贵”...再一找,又发现一个解决方案,HttpResponseBase.End 方法,MSDN描述如下:“在派生类中重写时,将当前缓冲的所有输出发送至客户端,停止执行请求的进程,并引发 EndRequest 事件”,换句话说,EndRequest就是End方法发出来了;而且在此之前“停止执行请求的进程”,这样Authentication Module就没有机会执行了,这样应该也不用去LogOn的Action了,哈哈,赶紧测试:
先使用Chrome看下响应代码
果然,如愿得到了401,把代码做了些相应的改变,放入HttpStatusResult中,测试,客户端果然得到了401,完成。
最后再提供一句废话,听说把web.config中的 <authentication />配置节点去掉的话也能得到期望结果,如果您有兴趣可以试试(这不符合我的需求,所以我没有做测试)。
我打算在服务器商把所处理的HTTP异常状态(400-599))状态一一返回给客户端组件,客户端收到各个状态码后根据号码及从服务器端返回的Description Content来抛出客户端的异常,结果在测试401时发现一个问题:在我的设想中,收到401,然后再去读取Response中的Status Description(我使用了自定义格式,详见上篇博文),结果出乎意料的是,服务器端发出了401,结果客户端没有抛出异常,而且按照接收成功的状态去了读取ATOM Feed的代码,而解析ATOM Feed时报错了,这让我很是诧异,经查看HttpStatusCode发现,返回的居然是200! RESTful的好处就是可以通过浏览器调用服务,把Url贴到浏览器中一看,原来返回的居然是LogOn视图...心中大概有数了,敢情MVC这家伙自做聪明,直接把401交给了Authentication Module去执行Unauthorized Handler了,整个过程类似在使用Authorize特性时用户没有登录一样(因为实际上在执行Authorization Filter时,也是通过HttpUnauthorizedResult实例将Response的StatusCode设置为401)。可是我现在使用的是客户端调用Web Service,你给我一个登录界面有啥用呢?再说了,我只是没有权限访问某个服务方法(Action),又不是没有登录,难道让我使用403去代替401么?但这不是我想要的,经过一番查找,发现在HttpApplication.EndRequest事件貌似可以,MSDN描述如下:“在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生”,最后一个事件应该是过了Authentication Module了吧,但是总觉得把这么一个事情放在Application中去处理,似乎有点太“重”了,凭什么其他的错误代码都可以作为ActionResult来处理,而一个401就能那么特殊呢,再说了,老衲一向痛恨“权贵”...再一找,又发现一个解决方案,HttpResponseBase.End 方法,MSDN描述如下:“在派生类中重写时,将当前缓冲的所有输出发送至客户端,停止执行请求的进程,并引发 EndRequest 事件”,换句话说,EndRequest就是End方法发出来了;而且在此之前“停止执行请求的进程”,这样Authentication Module就没有机会执行了,这样应该也不用去LogOn的Action了,哈哈,赶紧测试:
this.HttpContext.Response.Clear(); this.HttpContext.Response.StatusCode = 401; this.HttpContext.Response.End(); return new EmptyResult();
先使用Chrome看下响应代码
果然,如愿得到了401,把代码做了些相应的改变,放入HttpStatusResult中,测试,客户端果然得到了401,完成。
最后再提供一句废话,听说把web.config中的 <authentication />配置节点去掉的话也能得到期望结果,如果您有兴趣可以试试(这不符合我的需求,所以我没有做测试)。
相关文章推荐
- [原]使用ASP.NET MVC构建RESTful服务
- ASP.NET MVC + RESTful服务之HttpStatusResult
- SPRING MVC3.2案例讲解--使用 Spring 3 MVC HttpMessageConverter 功能构建 RESTful web 服务
- springMVC+json构建restful风格的服务
- ASP.NET MVC ApiController过滤器处理返回结果
- 在asp.net mvc中使用PartialView返回部分HTML段
- 使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标
- 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
- ASP.NET中MVC使用AJAX调用JsonResult方法并返回自定义错误信息
- ASP.NET状态服务及session丢失问题解决方案总结
- ASP.NET WebForm项目--页面正确返回404及500等状态
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动 解决办法
- ASP.NET MVC中Controller返回值类型ActionResult
- ASP.NET MVC – 关于Action返回结果类型的事儿(上)
- 无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动
- 无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动
- 在asp.net mvc中使用PartialView返回部分HTML段
- 在asp.net mvc中使用PartialView返回部分HTML段
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【外传】——Attribute Routing
- 无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动