У меня возникла проблема с решением архитектуры приложения ASP MVC, которое обрабатывает html-страницы и веб-службы через ServiceStack.ServiceStack API и ASP MVC Аутентификация двумя способами
Приложение работает в базовом URL-адресе, например «http://myapplication.com», а SS живет в «http://myapplication.com/api», потому что это самый простой способ настроить оба.
В целом все работает нормально, но когда я достиг части авторизации и аутентификации, я застрял.
Для этого мне нужны файлы cookie приложения, так как ASP обычно выполняет FormsAuthentication, и пользователи будут проходить через экран входа в систему и могут использовать действия и контроллеры, если используется атрибут «Авторизовать». Это типично для ASP, поэтому у меня нет проблем с этим, например «http://myapplication.com/PurchaseOrders».
С другой стороны, клиенты моего приложения будут использовать мою веб-службу api из javascript. Эти веб-службы также будут отмечены в некоторых случаях атрибутом «Аутентификация» ServiceStack. Например, «http://myapplication.com/api/purchaseorders/25» должен будет проверить, может ли пользователь просмотреть этот конкретный заказ на поставку, в противном случае отправить 401 Unauthorized, чтобы javascript мог обрабатывать эти случаи и отображать сообщение об ошибке.
И последнее, но не менее важное: другая группа пользователей будет использовать мой API через токен, используя любое внешнее приложение (возможно, Java или .NET). Поэтому мне нужно решить два типа аутентификации: один с использованием имени пользователя и пароля, другой - с помощью токена и сделать их постоянными, поэтому, как только они будут аутентифицированы в первый раз, следующие вызовы быстрее решаются из API.
Это код, который у меня есть до сих пор, я очень просто прояснил пример.
[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();
}
Как для проверки подлинности я использую этот класс
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);
}
}
О функции Настройки из AppHost Я настраиваю свой собственный класс аутентификации, чтобы использовать его в качестве значения по умолчанию. Думаю, я должен создать еще один класс и добавить его здесь, чтобы обработать сценарий токенов.
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new MyCredentialsAuthProvider(appSettings)
}, htmlRedirect: "~/Account/Logon"));
До сих пор ServiceStack работает должным образом. Я могу отправить сообщение в/auth/credentials, передавая имя пользователя и пароль, и он хранит эту информацию, поэтому следующий вызов службы, на который уже разрешен запрос, отлично!
Вопрос, который мне нужен, заключается в том, как вызвать (и, возможно, установить где-нибудь в SS) пользователя, который входит в систему с моего контроллера учетной записи. Если вы видите первый блок кода, я пытаюсь вызвать веб-службу (похоже, что я делаю это неправильно), и она работает, но следующий вызов любой веб-службы выглядит неаутентифицированным.
Пожалуйста, не указывайте мне учебные пособия по ServiceStack, я был там последние два дня и до сих пор не могу понять это.
Большое спасибо.
У меня нет компьютера с VS, чтобы проверить ваш ответ, хотя он выглядит хорошо. Попробует сегодня вечером. Благодаря! – coffekid
Это действительно работало. Большое спасибо! – coffekid