我有一个 ASP.NET MVC 应用程序,它具有.asmx Web服务
我编写了一个动作过滤器属性,我希望在Web服务上的Web方法上使用,检查UserID和Password的Request标头,如果无效或不存在,则抛出未经授权的响应代码。
然而,他们似乎没有被召唤!断点不会被击中。
首先,使用 MVC 属性是一种可接受的方式来授权在 ASMX Web服务上调用的Web服务吗?
其次,是否有更好/更有效的方式来授权Web服务方法调用?
答案 0 :(得分:7)
在回答您的第一个问题时, ASMX 网络服务无法触发 MVC 过滤器和 Web API 过滤器。
操作过滤器是 MVC 管道的一部分,在执行控制器(或API控制器)上的操作方法之前(或之后)触发。它们只能在 MVC 框架中使用。
操作过滤器覆盖 MVC 控制器(OnActionExecuting
)上的虚拟方法。由于只有 MVC 控制器具有此类方法,并且只有 MVC 管道检查它们
更糟糕的是, ASMX 服务默认使用 SOAP 协议而不是 HTTP 协议。 SOAP 服务无法访问HTTP上下文(例如HttpContext.Current.User
)或 HTTP 框架。
可以将 的Web服务配置为使用 HTTP协议。但是,即使这样, MVC 特定的属性也无济于事。
验证传统 ASMX 服务的方法
理想的方式是add a Service Reference到 MVC 4 项目,像{{1}中的任何类库方法一样调用 ASMX 方法安全的Action方法或 Web API 方法。
这样,您就可以利用 MVC 或 Web API 身份验证过滤器。
如果您希望直接保护 ASMX 服务,可以通过配置 ASMX 服务使用<来检查[Authorize]
表单身份验证em> HTTP 协议。
HttpContext.Current.User
答案 1 :(得分:2)
我认为为Authorization创建自定义属性过滤器是个好主意。 您可以创建自定义授权的服装过滤器。
namespace CustomeFilters
{
class CustomAuthorize : AuthorizeAttribute
{
private const string _securityParameter = "someCredentials"; // Name of the url parameter.
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (Authorize(filterContext))
{
return;
}
HandleUnauthorizedRequest(filterContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//Your logic for unauthorized access
HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
string deviceId = request.Params[_securityParameter]; //Your may have values in request headers
if (!string.IsNullOrEmpty(_securityParameter ))
{
base.HandleUnauthorizedRequest(filterContext);
}
//You can also check if request is authorized as basic authentication or not
//if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
}
private bool Authorize(AuthorizationContext actionContext)
{
HttpRequestBase request = actionContext.RequestContext.HttpContext.Request;
// Your authorisation logic goes here..
//actionContext.RequestContext.HttpContext.Response.StatusCode = 400;
//actionContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = "Request from invalid device !" };
bool success = <true/false>;//Acording to authorisation logic
return success;
}
}
它会像这样使用
[CustomAuthorize]
public ActionResult Test()
{
ViewBag.Message = "Hello World.";
return View();
}
这里是从MVC授权继承Authorize属性。 它覆盖了两种方法:
- OnAuthorisation:这里是您的授权逻辑。这是检查未经授权的请求。
- HandleUnauthorizedRequest:这里用于处理未经授权的访问的逻辑。它正在调用它的parrent类 HandleUnauthorizedRequest执行处理未授权 访问。
醇>
答案 2 :(得分:2)
问题的第一部分:
使用MVC属性是一种可接受的授权Web服务的方式 ASMX网络服务?
根据@DaveAlperovich
ASMX网络服务无法触发MVC过滤器和Web API过滤器。
但是从这个SO答案
由于ASMX也是ASP.NET管道的服务器,你可以使用 HttpModules,它为您提供了很多控制方式和方式 进行。
这是一个参考和一个例子: http://msdn.microsoft.com/en-us/library/aa719858%28VS.71%29.aspx
如果你想让它非常像“MVC”那么你会写一个自定义 http模块,检查webservice的属性,如 [授权]等。由于ASP.NET MVC是开源的,你可以使用 作为参考的部分,他们如何检查属性等 然后将其构建到您的HTTPModule中。
所以我仍然无法找到关于你的第一个问题的正式文件
我仍然怀疑使用MVC属性时某些事件不会触发Web服务
<强>更新强>
来到ASMX(source)
使用XML信息集作为其消息格式,并依赖于 应用层协议,最值得注意的是超文本传输协议 (HTTP)或简单邮件传输协议(SMTP),用于消息 谈判和传播
从Scott Hanselman Blog开始,默认情况下,请求不由ASP.NET MVC路由机制处理
为什么ASP.NET MVC没有抓住请求?两个原因。首先,有 RouteCollection上的一个名为RouteExistingFiles的选项。它被设定为 默认情况下为false会导致ASP.NET MVC自动跳过 磁盘上存在文件时的路由。
第二个Qst:
是否有更好/更有效的授权Web服务方法的方法 呼叫?
您可以使用SOAP标头中发送的凭据来授权Web服务
以下是一个例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace AuthExample
{
public class Authentication : SoapHeader
{
public string User;
public string Password;
}
/// <summary>
/// Summary description for webrusterapi
/// </summary>
[WebService(Namespace = "http://xxxx.xxx")]
[WebServiceBinding(ConformsTo = Profiles.BProfile1)]
[System.ComponentModel.ToolboxItem(false)]
public class Webrusterapi: System.Web.Services.WebService
{
public Authentication authHeader;
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
[SoapHeader("authHeader")]
public string HelloWorldWithCredentials()
{
if (authHeader.User != "Foouser" & authHeader.Password != "barPassword")
{
new SoapException("Fault occurred", SoapException.ClientFaultCode);
}
return string.Format("Hello {0}", authHeader.User);
}
}
}
答案 3 :(得分:2)
MVC和Web API管道与旧式的.ASMX Web服务不直接兼容。这就是为什么当您将这些属性放在Web方法上时,这些属性不会触发。根据您的代码库,您可以将代码转换(重写)到Web API 2平台,这是新推荐的编写服务的方式。与传统的Web服务(.asmx)相比,这具有以下优势。
xml
和json
。对于客户端来说,这可以非常容易,因为发送和接收的有效负载通常更简单,更不用说轻量级(.asmx服务中使用的SOAP信封非常臃肿。)然后问题变为&#34;您是否应该转换现有代码?&#34; 取决于:
我要避免的是在Web API中编写一个包装器来调用Web服务。
现在假设您要继续使用.ASMX Web服务并解决问题How can you execute Authorization on a web service
。
传统的身份验证方法是在SOAP标头中包含身份验证信息。使用现有的SoapHeaderAttribute
可以轻松完成此操作。
SoapHeaderAttribute
放在您的网络方法我更喜欢创建我的其他服务继承的抽象基础服务。这应该创建一个少一点重复的代码。这是一个没有身份验证详细信息的完整示例。在这个例子中,我使用传统的用户名和密码,但实际上它可以是任何东西(令牌,密码哈希,HMAC信息等),因为这个问题有点超出了我不会进入身份验证细节的范围。 / p>
using System.Web.Services;
using System.Web.Services.Protocols;
public abstract class AuthorizedWebService : System.Web.Services.WebService
{
// authentication info
public Authentication Authentication { get; set; }
// execute the actual authentication and authorization check
protected virtual void Authorize()
{
// check the Authentication instance object (passed in credentials)
// if not authenticate or authorized
// throw new System.Security.Authentication.AuthenticationException();
}
}
// authentication info
public class Authentication : SoapHeader
{
public string Username { get; set; }
public string Password { get; set; }
}
[WebService(Namespace = "http://tempuri.org/")]
public class MyTraditionalWebService : AuthorizedWebService
{
[WebMethod(Description = "Some web method.")]
[SoapHeader("Authentication")]
public string HelloWorld()
{
base.Authorize();
return "Hello " + base.Authentication.Username;
}
}
您可以使用Active Directory身份验证。然后,在c#中,客户端将使用NetworkCredential类传递凭据。基本上客户端执行的操作是将身份验证凭据应用于HTTP标头。我发现这个good SO answer代表了在进行HTTP调用时NetworkCredential类实际转化为什么。您必须配置IIS,以便在请求到达方法之前进行身份验证和授权。您也可以直接在Web方法中执行授权的自定义代码(类似于上面的内容),但不能用于身份验证。
对于表单身份验证,使用与上述指定Traditional / defacto
方式相比具有任何优势的Web服务没有好办法。但是,如果您已经拥有(现在)包含.asmx服务的网站设置,那么您可以在web.config
中包含该服务的授权,前提是客户端已经对您的网站进行了身份验证。
您还可以编写一个自定义HttpModule来处理身份验证和可能的授权。这种方法的优点是您可以将Web服务中的业务逻辑与身份验证/授权分离。这是一把双刃剑,但你必须维护一个解析url的模块,以及查看请求是否被授权的预期方法。这可能导致脆弱的耦合。