Mam projekt, w którym korzystam z Identity (Core). Czy lepiej bezpośrednio korzystać z UserManagera
i innych, czy może lepiej napisać jakiś IAuthService
+ implementację i to ich używać?
Wszystko zależy od tego jaka jest skala projektu, czy użyta technologia może się zmienić, czy użycie nie-wyabstrachowanej autentykacji utrudni testowanie itp. Moim zdaniem zazwyczaj nie ma takiej potrzeby.
Czy zdarzyło się komuś wymieniać Idenitity na inną bibliotekę? Czy istnieje w ogóle jakaś alternatywa dla Identity?
Nawet jeśli nie ma obecnie alternatywy, to nic nie stoi chyba na przeszkodzie, żeby taką sobie samemu w swoim projekcie wdrożyć.
Nie piszę w Core, ale nawet jeśli Identity jest świetne i ma wbudowane wszystko, co może być potrzebne, to trzeba by je referencjonować we wszystkich warstwach aplikacji. A to może nie być ładne, dlatego ja bym prawdopodobnie opakował.
Powiedzmy, że opakowuję UserManager<User>
w IUserManager
(wydaje mi się, że AuthService
to lepsza nazwa dla usługi logującej, rejestrującej itd. operującej bezpośrednio na viewmodelach). Czy wtedy interfejs + implementacja mogą wyglądać np. tak:
public interface IUserManager
{
int? GetUserId(ClaimsPrincipal user);
string GetUserName(ClaimsPrincipal user);
Task<Result> CreateAsync(User user, string password);
}
public class UserManager : IUserManager
{
// UserManager from Identity
private readonly UserManager<User> _userManager;
public UserManager(UserManager<User> userManager)
{
_userManager = userManager;
}
public int? GetUserId(ClaimsPrincipal user)
{
var isLoggedIn = int.TryParse(_userManager.GetUserId(user), out int userId);
return isLoggedIn ? userId : (int?) null;
}
public string GetUserName(ClaimsPrincipal user)
{
return _userManager.GetUserName(user);
}
public async Task<Result> CreateAsync(User user, string password)
{
var result = await _userManager.CreateAsync(user, password);
if (!result.Succeeded)
{
// TODO log errors
return new Result(new Error(ErrorName.NotKnown));
}
return new Result(null);
}
}
Jakby nie rozumiem po co metody przyjmują ClaimsPrincipal
. Jak dla mnie taki wrapper powinien ukrywać wszystkie szczegóły implementacyjne.
Yyy, nie rozumiem. Skoro metoda CreateAsync
w UserManager<User>
przyjmuje ClaimsPrincipal
, to co powinienem przekazać do wrappera?
EDIT:
Chodzi o to, żeby użyć ClaimsPrincipal.Current
?
No najlepiej to chyba nic. Ja bym widział taki interfejs:
ISecurityContext
{
int GetCurrentUserId();
string GetCurrentUserName();
int GetCurrentUserUnitId();
}
I tak dalej dla wszystkich claimsów mających biznesowe znaczenie, i żadnego Create tutaj (bo to nie jest coś, co jest potrzebne w całej aplikacji).
Bo jeśli robić taki wrapper, który tylko opakowuje metody z UserManager
, to ja nie wiem jaki jest z tego zysk.
OK, teraz widzę.
- Właściwie to implementacje tych metod mogę zrobić bez korzystania z
UserManagera
z Identity (patrzyłem na implementacje w Identity, są dość krótkie). Warto? Nie trzeba by było wtedy przy każdym żądaniu tworzyćUserManagera
. - Czyli w
AuthService
powinienem korzystać bezpośrednio zUserManagera
z Identity?AuthService
potrzebuje dość specjalistycznych metodUserManagera
, które raczej nigdzie indziej nie zostaną użyte. - Co, jeśli korzystałbym z małej biblioteki, której wszystkie metody są mi potrzebne i wszystkie są dość dobrze dostosowane do całej aplikacji? Skoro pisanie wrappera, który tylko opakowuje, nie ma sensu, a biblioteka może się zmienić, to co należy zrobić?