2014-11-12 3 views
1

У меня есть эта служба WCF, и я пытаюсь применить в ней механизм аутентификации и авторизации.
Это мой первый раз, чтобы сделать это, что у меня есть это web.config serviceModel тег для службы:Почему Thread.CurrentPrincipal.Identity.IsAuthenticated всегда false?

<system.serviceModel> 
<services> 
    <service name="RoleBasedServices.SecureServiceExternal" behaviorConfiguration="externalServiceBehavior"> 
    <endpoint contract="AuthService.IService1" binding="wsHttpBinding" bindingConfiguration="wsHttpUsername" /> 
    </service> 
</services> 
<bindings> 
    <wsHttpBinding> 
    <binding name="wsHttpUsername"> 
     <security mode="Message"> 
     <message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false" /> 
     </security> 
    </binding> 
    </wsHttpBinding> 
</bindings> 
<behaviors> 
    <serviceBehaviors> 
    <behavior> 
     <!--To avoid disclosing metadata information, set the values below to false before deployment--> 
     <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
     <!--To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information--> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
    </behavior> 
    <behavior name="externalServiceBehavior"> 
     <serviceAuthorization principalPermissionMode="UseAspNetRoles" /> 
     <serviceCredentials> 
     <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" /> 
     <serviceCertificate findValue="RPKey" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/> 
     </serviceCredentials> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<protocolMapping> 
    <add binding="basicHttpsBinding" scheme="https" /> 
</protocolMapping>  
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 

То, что я хочу сделать, это очень просто, я не знаю, Мне нужны все те теги, которые я просто пытаюсь. То, что я хочу сделать, это на стороне клиента, чтобы добавить ссылку на службу и первым называют MyLogin:

AuthService.Service1Client s = new AuthService.Service1Client(); 
    s.Login(); 

Затем вызовите другой ограниченный метод и пусть это будет GetData:

s.GetData() 

В сторона службы в Login метод, и только для целей тестирования, я делаю это:

public void Login() 
{ 
    Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Bob"), new[] { "Admin" }); 
    FormsAuthentication.SetAuthCookie("BobUserName", false); 
} 

Ап restricte d будет:

[PrincipalPermission(SecurityAction.Demand, Role = "Admin")] 
public void GetData() 
{ 
    return "Hello"; 
} 

Что у меня есть на службе и у клиента, что мне не хватает? Каждый раз, в отладке, я проверяю Thread.CurrentPrincipal в методе Login. Найден Thread.CurrentPrincipal.Identity.IsAuthenticated равно true, но даже если клиент называет метод GetData(), это Access Denied.
PS: Я использую консольное приложение для выполнения своих тестов, не имеет значения?
Thanks

+0

не должен выполнять роль PrincipalPermision "BUILTIN \\ Administrator"? – Prokurors

ответ

2

Это very nice article, которые могут привести к решению проблемы.

Общая идея заключается в том, что у вас есть 2 объекта для Принципала. HttpContext.Current.User и Thread.CurrentPrincipal. Вы устанавливаете Thread.CurrentPrincipal в то время, когда HttpContext.Current.User уже создан, а его значение остается по умолчанию.
Вы можете попробовать что-то вроде:

HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("Bob"), new[] { "Admin" });
0

Причины вызовов в GetData() отрицаются происходит потому, что WCF ничего не знаю о куках Forms Authentication, который был установлен во время Login() не знает.

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

Набор печенья в Login():

var cookie = FormsAuthentication.GetAuthCookie(username, true); 
var ticket = FormsAuthentication.Decrypt(cookie.Value); 

HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(ticket), null); 
FormsAuthentication.SetAuthCookie(HttpContext.Current.User.Identity.Name, true); 

Затем в консоли приложения:

public static void TestLoginAndGetData() 
{ 
    var sharedCookie = string.Empty; 

    using (var client = new YourClient()) 
    using (new OperationContextScope(client.InnerChannel)) 
    { 
     client.Login("username", "password"); 

     // get the cookie from the response 
     HttpResponseMessageProperty response = (HttpResponseMessageProperty) 
      OperationContext.Current.IncomingMessageProperties[ 
      HttpResponseMessageProperty.Name]; 
     sharedCookie = response.Headers["Set-Cookie"]; 

     // add it to the request 
     HttpRequestMessageProperty request = new HttpRequestMessageProperty(); 
     request.Headers["Cookie"] = sharedCookie; 
     OperationContext.Current.OutgoingMessageProperties[ 
      HttpRequestMessageProperty.Name] = request; 

     var result = client.GetData(); 

     Console.WriteLine(result); 
    } 
} 

Вы могли бы также рассмотреть вопрос об изменении типа возвращаемого GetData() в string.

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