Правильный способ авторизации ASMX.NET веб-сервис от проекта MVC 4

У меня есть ASP.NET MVC приложение, которое имеет .asmx веб-сервис

Я написал атрибут фильтра действий, который я хотел использовать в веб-методах веб-службы, чтобы проверить заголовки запросов для идентификатора пользователя и пароля и бросить несанкционированный код ответа, если он недействителен или отсутствует.

тем не менее, они не появляются, чтобы получить вызов! Точки останова просто не попадают.

во-первых, используя MVC атрибуты приемлемый способ авторизация веб-службы вызывается на asmx и веб-сервиса?

во-вторых, есть ли лучший / более эффективный способ авторизации вызовов методов веб-службы?

4 ответов


в ответ на ваш первый вопрос, MVC фильтры и Web API фильтры не могут быть вызваны asmx и веб-служб.

  1. фильтры действий являются частью MVC выполняется конвейер, запускаемый до (или после) метода действия на контроллере (или контроллере API). Они могут использоваться только в MVC основы.

    действие фильтра переопределить виртуальный метод MVC (OnActionExecuting). Как только MVC контроллеры имеют такие методы, и только в MVC трубопровод проверяет их

  2. что еще хуже,asmx и сервисы, по умолчанию, используйте мыло протокол, а не адресу http протокол. мыло службы не могут получить доступ к контекстам HTTP (например,HttpContext.Current.User) или адресу http основы.

    Web услуги можете быть настроен на использование HTTP-протокол. Но даже тогда ... --7-->MVC конкретные атрибуты вам не помогут.


способы аутентификации legacy asmx и услуги

  • идеальный способ-это добавить ссылку на службу на MVC 4 проект, вызывающий ваш asmx и метод, как любой метод библиотеки классов из Ан [Authorize] защищенный метод действия или Web API метод.

    таким образом, вы можете использовать MVC или Web API фильтры аутентификации.

  • если вы предпочитаете защитить свой asmx и обслуживание сразу, вы можете проверить к HttpContext.Current.User с проверкой подлинности форм, настроив asmx и сервис использовать адресу http протокол.

в вашей сеть.config

<location path="SecuredMethod.asmx">
  <system.web>
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
  </system.web>
</location> 

.Служба ASMX и AuthorizeAttribute

конвейер MVC и Web API напрямую не совместим со старым стилем .Веб-службы ASMX. Вот почему эти атрибуты не срабатывают, когда вы размещаете их в своих веб-методах. В зависимости от вашей базы кода Вы можете преобразовать (переписать) свой код на платформу Web API 2, которая является новым рекомендуемым способом написания сервисов. Это имеет следующие преимущества перед традиционными веб-службами (.службы ASMX.)

  1. Формат Данных - клиент может определить формат полученных данных. В настоящее время 2 из поддерживаемых форматов коробки xml и json. Это может быть значительно проще в работе с клиентом, так как полезная нагрузка, отправленная и полученная, обычно намного проще, не говоря уже о легком весе (мыло, используемое в .службы asmx очень раздуты.)
  2. Фильтры Действий - вы можете воспользоваться атрибут Authorize, а также настраиваемые фильтры действий для выполнения предварительной и последующей обработки общих действий.
  3. намерения с HTTP глаголом - действия становятся основанными на HTTP вместо SOAP. Вы можете использовать методы http, чтобы дать прямой смысл вашим открытым веб-методам (GET, POST, PUT, DELETE).
  4. простота использования на всех платформах разработки - при прочих равных условиях гораздо проще писать против веб-api метод, чем метод ASMX, потому что полезная нагрузка и ответы легче перевести из-за отсутствия раздувания. Некоторые стандартные типы также легче переводить, которые обычно включены в язык определения WSDL, например nullable types и экземпляры .net DateTime.

тогда вопрос становится " следует ли конвертировать существующий код?" это зависит от:

  • у вас есть существующие клиенты, которые уже называют вашу базу кода это также нужно будет преобразовать? Это может быть невозможно, если эти клиенты находятся вне вашего контроля (например, если эти вызывающие клиенты созданы вашими клиентами).
  • размер или количество методов, которые вы уже создали. Если вы только начинаете свой проект, его все еще можно легко преобразовать в веб-Api, но если у вас уже есть существенная база кода с модульными тестами, это может быть экономически неэффективно.
  • если у вас уже есть контракт, определенный с внешними сторонами вокруг вашего кода. Можно создать определения в WSDL и запустить разработку клиента и разработку на стороне сервера одновременно на основе этого контракта, если это так, вам нужно будет убедить разработчика(разработчиков) на стороне клиента/стороны преобразовать в контракт веб-API, но это может быть невозможно.

чего бы я избегал, так это написания оболочки в веб-API, которая вызывает веб-интерфейс Услуга.

  • он добавляет физический уровень между вызовами (пересечение другой границы сети), который увеличивает задержку между отправленным сообщением и полученным ответом
  • это добавляет еще один слой кода, который вы должны создать и поддерживать
  • дополнительные (ненужные) слои также, как это делает его очень легко непреднамеренно ввести дефекты, когда вы должны реализовать изменения

.Asmx и разрешение

Давайте теперь предположим, что вы хотите продолжить .Веб-службы ASMX и ответьте на вопрос How can you execute Authorization on a web service.

традиционный / defacto

традиционный способ аутентификации-включить информацию аутентификации в заголовок SOAP. Это может быть легко достигнуто с помощью существующего SoapHeaderAttribute.

  • место SoapHeaderAttribute на ваш веб-метод(ы)
  • создайте объект аутентификации, который будет содержать переданные аргументы, используемые для проверка подлинности
  • написать метод аутентификации

Я предпочитаю создавать абстрактную базовую службу, которую наследуют мои другие службы. Это должно создать немного меньше дубликатов кода. Вот полный пример без деталей аутентификации. В этом примере я использую традиционное имя пользователя и пароль, но на самом деле это может быть что угодно (токен, хэш пароля, информация HMAC и т. д.) , И поскольку это немного выходит за рамки вопроса, я не буду входить данные аутентификации.

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

можно использовать проверку подлинности Active Directory. В c# клиент затем передаст учетные данные, используя NetworkCredential класса. По сути, клиент применяет учетные данные проверки подлинности к заголовку HTTP. Я нашел это довольно хорошо так ответ о том, что класс NetworkCredential фактически переведет при выполнении HTTP-вызова. У вас есть чтобы настроить IIS так, чтобы проверка подлинности и авторизация происходили до того, как запрос достигнет вашего метода. Вы также можете выполнить пользовательский код для авторизации непосредственно в своих веб-методах (аналогично приведенному выше), но не для аутентификации.

Проверка Подлинности С Помощью Форм

Что касается проверки подлинности форм, нет хорошего способа сделать это с помощью веб-служб, которые имеют какие-либо преимущества над указанными выше Traditional / defacto путь. Однако, если у вас уже есть веб сайт, который (теперь) включая ваш .службы asmx, тогда вы можете включить авторизацию для службы в web.config предполагая, что клиент уже прошел аутентификацию на вашем сайте.

Пользовательский HttpModule

вы также можете написать пользовательский HttpModule, который обрабатывает аутентификацию и возможную авторизацию. Профи этого подхода заключается в том, что вы отделяете бизнес-логику в веб-службе от аутентификации/авторизации. Это обоюдоострый меч, хотя, как вам придется поддерживайте модуль, который анализирует url, а также предполагаемый метод, чтобы увидеть, авторизован ли запрос. Это может привести к хрупкому соединению.


Я думаю, что создание пользовательского фильтра атрибут для авторизации будет хорошей идеей. Вы можете создать свой костюм фильтр, который настраивает авторизацию, как это.

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();
    }

здесь вы наследуете атрибут Authorize от авторизации MVC. Он переопределяет два метода:

  1. OnAuthorisation: здесь ваша логика авторизации идет.Здесь он проверяет для handelling несанкционированный запрос.
  2. HandleUnauthorizedRequest: здесь логика для передачи несанкционированного доступа идет.Он зовет, это класс паррента. HandleUnauthorizedRequest осуществить для обработки несанкционированного доступ.

первая часть вашего вопроса:

использует атрибуты MVC приемлемый способ авторизации веб-службы, вызываемой веб-служба ASMX?

согласно @DaveAlperovich

фильтры MVC и фильтры Web API не могут запускаться веб-службами ASMX.

но из этого так ответ

поскольку ASMX также являются сервером ASP.NET трубопровод, вы могли бы просто использовать Модули http, что дает вам много контроля на пути и пути из.

вот ссылка и пример: http://msdn.microsoft.com/en-us/library/aa719858%28VS.71%29.aspx

Если вы хотите сделать его очень "похожим на MVC", тогда вы напишете пользовательский http-модуль, который проверяет webservice на такие атрибуты, как [Санкционировать] и т. д. Так ASP.NET MVC является открытым исходным кодом, вы можете просто использовать части этого в качестве ссылки, как они проверяют атрибуты и т. д. затем создайте его в свой HTTPModule.

ссылка на SO вопрос

так что я все еще не мог найти хорошо официального документа относительно вашего первого вопроса и я все еще сомневаюсь в этом!--33-->некоторые события не срабатывают для веб-службы при использовании атрибутов MVC

обновление

при переходе на ASMX (источник)

использует набор данных XML для свой формат сообщения, и полагается на протоколы прикладного уровня, в частности протокол передачи гипертекста (HTTP) или простой протокол передачи почты (SMTP), для сообщения переговоры и передача

С Блог Скотта Хансельмана запрос по умолчанию не обрабатывается ASP.NET механизм маршрутизации MVC

почему нет ASP.NET MVC захватить запрос? По двум причинам. Во-первых, вариант на RouteCollection называется RouteExistingFiles. Он настроен на false по умолчанию, что вызывает ASP.NET MVC для автоматического пропуска маршрутизация, когда файл существует на диске.

Второй Qst:

есть ли лучший / более эффективный способ авторизации метода веб-службы звонки?

вы можете использовать учетные данные, отправленные в заголовке SOAP для авторизации веб-службы

вот пример:

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);
        }
    }
}