Ich habe Probleme beim Lösen der Architektur einer ASP MVC-Anwendung, die HTML-Seiten und Web-Services über ServiceStack Server verwaltet.ServiceStack API und ASP MVC Authentifizierung auf zwei Arten
Die Anwendung lebt in der Basis-URL z. B. "http://myapplication.com" und SS lebt in "http://myapplication.com/api", weil es der einfachste Weg ist, beide zu konfigurieren.
Im Allgemeinen funktioniert alles gut, aber wenn ich den Teil der Autorisierung und Authentifizierung erreicht habe, ist, wo ich feststecke.
Zum einen brauche ich die Anwendung behandeln Cookies als ASP normalerweise FormsAuthentication durch, und Benutzer würden durch einen Login-Bildschirm und könnte Aktionen und Controller zu konsumieren, wenn das Attribut "Authorize" verwendet wird. Das ist typisch für ASP, also habe ich kein Problem damit, zB "http://myapplication.com/PurchaseOrders".
Auf der anderen Seite, Kunden meiner Anwendung werden meine Web-Service-API von Javascript konsumieren. Diese Web Services werden in einigen Fällen auch mit dem Attribut "Authenticate" von ServiceStack versehen. Zum Beispiel "http://myapplication.com/api/purchaseorders/25" müsste validieren, wenn der Benutzer diese bestimmte Bestellung anzeigen kann, sonst senden Sie eine 401 Unauthorized, so dass Javascript diese Fälle behandeln und die Fehlermeldung anzeigen kann.
Last but not least wird eine andere Gruppe von Benutzern meine API mit einem Token nutzen, indem sie irgendeine externe Anwendung (wahrscheinlich Java oder .NET) benutzt. Also muss ich zwei Arten der Authentifizierung lösen, eine mit Benutzernamen und Passwort, die andere mit dem Token und sie persistent machen. Sobald sie das erste Mal authentifiziert werden, sind die nächsten Aufrufe schneller von der API zu lösen.
Dies ist der Code, den ich bisher habe, ich habe es sehr einfach gesagt, um das Beispiel zu verdeutlichen.
[HttpPost]
public ActionResult Logon(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
JsonServiceClient client = new JsonServiceClient("http://myapplication.com/api/");
var authRequest = new Auth { provider = CredentialsAuthProvider.Name, UserName = model.UserName, Password = model.Password, RememberMe = model.RememberMe };
try
{
var loginResponse = client.Send(authRequest);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(loginResponse.UserName, false, 60);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
Response.Cookies.Add(cookie);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Test");
}
}
catch (Exception)
{
ModelState.AddModelError("", "Invalid username or password");
}
}
return View();
}
Wie für den Authentifizierungs-Provider ich diese Klasse bin mit
public class MyCredentialsAuthProvider : CredentialsAuthProvider
{
public MyCredentialsAuthProvider(AppSettings appSettings)
: base(appSettings)
{
}
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
//Add here your custom auth logic (database calls etc)
//Return true if credentials are valid, otherwise false
if (userName == "testuser" && password == "nevermind")
{
return true;
}
else
{
return false;
}
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
//Fill the IAuthSession with data which you want to retrieve in the app eg:
session.FirstName = "some_firstname_from_db";
//...
session.CreatedAt = DateTime.Now;
session.DisplayName = "Mauricio Leyzaola";
session.Email = "[email protected]";
session.FirstName = "Mauricio";
session.IsAuthenticated = true;
session.LastName = "Leyzaola";
session.UserName = "mauricio.leyzaola";
session.UserAuthName = session.UserName;
var roles = new List<string>();
roles.AddRange(new[] { "admin", "reader" });
session.Roles = roles;
session.UserAuthId = "uniqueid-from-database";
//base.OnAuthenticated(authService, session, tokens, authInfo);
authService.SaveSession(session, SessionExpiry);
}
}
auf der Seite Konfigurieren Funktion von AppHost ich meine benutzerdefinierten Authentifizierungs Klasse setze es als Standard zu verwenden. Ich denke, ich sollte eine andere Klasse erstellen und sie hier hinzufügen, um das Token-Szenario zu behandeln.
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new MyCredentialsAuthProvider(appSettings)
}, htmlRedirect: "~/Account/Logon"));
Bis jetzt funktioniert ServiceStack wie erwartet. Ich kann einen Beitrag an/auth/credentials übergeben Benutzername und Passwort übergeben und es speichert diese Informationen, so nächsten Aufruf an einen Dienst ist die Anfrage bereits autorisiert, groß, so weit!
Die Frage, die ich wissen muss, ist, wie man den Benutzer, der sich von meinem Account-Controller anmeldet, anruft (und wahrscheinlich irgendwo in SS). Wenn Sie den ersten Codeblock sehen, versuche ich den Webservice anzurufen (sieht so aus, als würde ich es falsch machen) und es funktioniert, aber der nächste Aufruf eines Webdienstes sieht nicht authentifiziert aus.
Bitte weisen Sie mich nicht auf ServiceStack Tutorials, ich war die letzten zwei Tage dort und kann es immer noch nicht herausfinden.
Vielen Dank im Voraus. Hier
Ich habe keinen Computer mit VS, um deine Antwort zu testen, obwohl es gut aussieht. Werde es heute Abend versuchen. Vielen Dank! – coffekid
Es hat tatsächlich funktioniert. Danke vielmals! – coffekid