2013-03-11 10 views
13

Ich versuche, eine Windows Forms-Anwendung zu machen, die in einige Dienste von ASP.NET MVC WebAPI verfügbar macht, aber ich habe eine Menge Probleme mit der Authentifizierung/Anmeldung.MVC WebAPI-Authentifizierung von Windows Forms

Ich kann nicht scheinen, ein Beispiel zu finden, das nur zeigt, wie dies von Windows Forms zu tun ist, alles scheint sehr verworren und enthält eine Menge sehr tiefe Klempnerarbeit, oder scheint auf andere ASP.NET-Websites ausgerichtet und keine Windows-Formulare.

Gibt es etwas, das mir fehlt? Ist das nicht möglich? Oder ist es einfach nicht beabsichtigt? Ich habe Dinge wie diese gesehen .NET WebApi Authentication, die behaupten, es zu tun, aber ich sehe nicht, wie man Cookies von einem Windows Forms Standpunkt aus verwendet. Ich bin auch über http://blogs.msdn.com/b/webdev/archive/2012/08/26/asp-net-web-api-and-httpclient-samples.aspx gegangen und habe immer noch sehr wenig Glück gehabt.

Antwort

4

Sie können Token-basierte Authentifizierung verwenden. Hier finden Sie eine great article, die veranschaulicht, wie Sie einen benutzerdefinierten Aktionsfilter schreiben können, der die öffentliche/private RSA-Kryptographie verwendet.

+1

Ich bin ein bisschen verwirrt. Ich habe keine Aktionsfilter in Windows Forms. – Derek

+1

Ich beziehe mich auf eine Login-Authentifizierung, nicht wirklich Verschlüsselung. – Derek

+0

Sie sollten Aktionsfilter in Ihrer Web-API verwenden, um Ihre Aktionen zu schützen. Die WinForms-Anwendung wird als Client für die Aktionen fungieren, die ich vermute. Das verschlüsselte Token könnte auch den Benutzernamen enthalten, der auf Ihre Methode zugreift. So können Sie Authentifizierung erreichen und da Sie den Benutzer kennen, sogar Autorisierung mit diesem Ansatz. –

12

Erstellen Sie einfach Authentifizierungstoken auf der Serverseite und speichern Sie sie in Ihrer Datenbank oder sogar im Cache. Dann senden Sie dieses Token mit Anfragen aus Ihrer Win-Forms-Anwendung. WebApi sollte dieses Token die ganze Zeit überprüfen. Es ist gut genug und Sie haben die volle Kontrolle über Ihren Auth-Prozess.

mich Aktie Lassen Sie, wie es funktioniert für mich:

Objekt mit Auth Details:

public class TokenIdentity 
{ 
    public int UserID { get; set; } 

    public string AuthToken { get; set; } 

    public ISocialUser SocialUser { get; set; } 
} 

Web API Auth Controller:

public class AuthController : ApiController 
    { 
     public TokenIdentity Post(
      SocialNetwork socialNetwork, 
      string socialUserID, 
      [FromUri]string socialAuthToken, 
      [FromUri]string deviceRegistrationID = null, 
      [FromUri]DeviceType? deviceType = null) 
     { 
      var socialManager = new SocialManager(); 

      var user = socialManager.GetSocialUser(socialNetwork, socialUserID, socialAuthToken); 

      var tokenIdentity = new AuthCacheManager() 
       .Authenticate(
        user, 
        deviceType, 
        deviceRegistrationID); 

      return tokenIdentity; 
     } 
    } 

Auth Cache Manager :

public class AuthCacheManager : AuthManager 
    { 
     public override TokenIdentity CurrentUser 
     { 
      get 
      { 
       var authToken = HttpContext.Current.Request.Headers["AuthToken"]; 
       if (authToken == null) return null; 

       if (HttpRuntime.Cache[authToken] != null) 
       { 
        return (TokenIdentity) HttpRuntime.Cache.Get(authToken); 
       } 

       return base.CurrentUser; 
      } 
     } 

     public int? CurrentUserID 
     { 
      get 
      { 
       if (CurrentUser != null) 
       { 
        return CurrentUser.UserID; 
       } 
       return null; 
      } 
     } 

     public override TokenIdentity Authenticate(
      ISocialUser socialUser, 
      DeviceType? deviceType = null, 
      string deviceRegistrationID = null) 
     { 
      if (socialUser == null) throw new ArgumentNullException("socialUser"); 
      var identity = base.Authenticate(socialUser, deviceType, deviceRegistrationID); 

      HttpRuntime.Cache.Add(
       identity.AuthToken, 
       identity, 
       null, 
       DateTime.Now.AddDays(7), 
       Cache.NoSlidingExpiration, 
       CacheItemPriority.Default, 
       null); 

      return identity; 
     } 
    } 

Auth Manager:

public abstract class AuthManager 
    { 
     public virtual TokenIdentity CurrentUser 
     { 
      get 
      { 
       var authToken = HttpContext.Current.Request.Headers["AuthToken"]; 
       if (authToken == null) return null; 

       using (var usersRepo = new UsersRepository()) 
       { 
        var user = usersRepo.GetUserByToken(authToken); 

        if (user == null) return null; 

        return new TokenIdentity 
        { 
         AuthToken = user.AuthToken, 
         SocialUser = user, 
         UserID = user.ID 
        }; 
       } 
      } 
     } 

     public virtual TokenIdentity Authenticate(
      ISocialUser socialUser, 
      DeviceType? deviceType = null, 
      string deviceRegistrationID = null) 
     { 
      using (var usersRepo = new UsersRepository()) 
      { 
       var user = usersRepo.GetUserBySocialID(socialUser.SocialUserID, socialUser.SocialNetwork); 

       user = (user ?? new User()).CopyFrom(socialUser); 

       user.AuthToken = System.Guid.NewGuid().ToString(); 

       if (user.ID == default(int)) 
       { 
        usersRepo.Add(user); 
       } 

       usersRepo.SaveChanges(); 

       return new TokenIdentity 
       { 
        AuthToken = user.AuthToken, 
        SocialUser = user, 
        UserID = user.ID 
       }; 
      } 
     } 
    } 

Global Action Filter:

public class TokenAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute 
{ 
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     if (actionContext.Request.RequestUri.AbsolutePath.Contains("api/auth")) 
     { 
      return; 
     } 

     var authManager = new AuthCacheManager(); 

     var user = authManager.CurrentUser; 

     if (user == null) 
     { 
      throw new HttpResponseException(HttpStatusCode.Unauthorized); 
     } 

     //Updates the authentication 
     authManager.Authenticate(user.SocialUser); 
    } 
} 

Global.asax Anmeldung:

GlobalConfiguration.Configuration.Filters.Add(new AuthFilterAttribute()); 

Die Idee ist, dass AuthCacheManager AuthManager erweitert und seine Methoden und Eigenschaften verziert. Wenn sich im Cache nichts befindet, gehe zur Datenbank.

+2

Haben Sie ein Codebeispiel? Darin's ist interessant, aber vielleicht hast du einen besseren. – hawbsl

+1

@hawbsl Ich habe meine Antwort aktualisiert. Hoffe, Sie werden dort alles Interessante finden und eine Idee für Ihre Bewerbung bekommen. – Andrei

+1

+50 +10 Ich habe es nicht ausprobiert, aber es sieht aus wie eine ausgezeichnete Roadmap zu folgen – hawbsl