Почему Thread.CurrentPrincipal.Identity.IsAuthenticated всегда ложно?

1

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

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

Ограниченный метод будет:

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

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

  • 0
    не должна ли роль PrincipalPermision быть "BUILTIN \\ Administrator"?
Теги:
authentication
wcf
current-principal

2 ответа

2

Вот очень хорошая статья, которая может привести к решению.

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

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

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

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

Установите cookie в 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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню