2013-04-10 3 views
1

Я знаю, что аутентификация в классе webservicehost не полностью соответствует стандартам проверки подлинности (возвращает 403, а не запрашивает другой набор учетных данных, когда пользователь вводит неверные учетные данные).Как реализовать аутентификацию WebServiceHost?

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

The type of authentication I want

код у меня есть для MYSERVICE выглядит следующим образом:

Imports System.IO 
Imports System.Text 
Imports System.ServiceModel 
Imports System.ServiceModel.Web 
Imports System.ServiceModel.Channels 

<ServiceContract()> 
Public Class myService 
    <OperationContract(), WebGet(UriTemplate:="/xml/{argument1}/{argument2}")> 
    Public Function XML(argument1 As String, argument2 As String) As Stream 
     requestCounter += 1 
     Console.WriteLine("xml data request at " & DateTime.Now.ToString() & ", request count= " & requestCounter) 
     Console.WriteLine(WebOperationContext.Current.IncomingRequest.UserAgent.ToString()) 
     Return _ReturnXML("<xmlresponse><data><argument1>" & argument1 & "</argument1><argument2>" & argument2 & "</argument2></data><server><serverlivesince>" & serverStart.ToString() & "</serverlivesince><pageservetime>" & DateTime.Now.ToString() & "</pageservetime><requestcount>" & requestCounter & "</requestcount></server></xmlresponse>") 
     'returns the first two parameters, and the time and date 
    End Function 

    Private Shared Function _ReturnXML(_result As String) As Stream 
     Dim data = Encoding.UTF8.GetBytes(_result) 

     WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml; charset=utf-8" 
     WebOperationContext.Current.OutgoingResponse.ContentLength = data.Length 

     Return New MemoryStream(data) 
    End Function 
End Class 

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

В моем главном классе я инстанцирован и открыл эту услугу как:

Dim varWebService = New WebServiceHost(GetType(MyWebService), New Uri("http://0.0.0.0/")) 
varWebService.Open() 

Может кто-нибудь дать мне код, чтобы реализовать эту простую аутентификацию? Или указать мне на тщательный учебник? Спасибо за любую помощь

+1

Что вы пробовали? Что ты получил? Чего ты ожидал? –

+0

Я еще ничего не пробовал, не знаю, как это сделать – rabbitt

+0

Stack Overflow, как правило, дружественный к вопросам, которые имеют конкретную проблему. Мы склонны хмуриться вопросами, которые требуют идей. –

ответ

2

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

Единственное изменение в коде будет

Dim varWebService = New AuthenticatedWebServiceHost(GetType(MyWebService), New Uri("http://0.0.0.0/")) 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.IdentityModel; 
using System.IdentityModel.Selectors; 
using System.ServiceModel; 
using System.ServiceModel.Web; 
using System.ServiceModel.Security; 
using System.ServiceModel.Description; 

namespace StackOverflow 
{ 
    public class AuthenticatedWebServiceHost : WebServiceHost 
    { 
     public AuthenticatedWebServiceHost(Type type, Uri url) 
     { 
      IDictionary<string, ContractDescription> desc = null; 
      base.InitializeDescription(type, new UriSchemeKeyedCollection()); 
      base.CreateDescription(out desc); 
      var val = desc.Values.First(); 

      WebHttpBinding binding = new WebHttpBinding(); 
      binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly; 
      binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 

      base.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; 
      base.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator(); 

      base.AddServiceEndpoint(val.ContractType, binding, url); 
     } 

     //Possible next question: 
     //"How can I get the name of the authenticated user?" 
     public static string UserName 
     { 
      get 
      { 
       if (OperationContext.Current == null) return null; 
       if (OperationContext.Current.ServiceSecurityContext == null) return null; 
       if (OperationContext.Current.ServiceSecurityContext.PrimaryIdentity == null) return null; 
       return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name; 
      } 
     } 



     public class CustomUserNamePasswordValidator : UserNamePasswordValidator 
     { 
      public override void Validate(string userName, string password) 
      { 
       //Your logic to validate username/password 
       if (userName != password) 
        throw new SecurityAccessDeniedException(); 
      } 
     } 
    } 
} 
+0

На самом деле я не могу заставить это работать. Есть ли вероятность, что вы можете предоставить рабочий пример проекта с образцовой функцией? Благодаря, – rabbitt

Смежные вопросы