Простая аутентификация/авторизация на основе токенов в asp.net ядро для хранилища данных Mongodb
мне нужно реализовать довольно простой механизм auth С в основном 2 ролями:Owners
и Users
. И я думаю, что наличия перечисления для этого будет достаточно. Само приложение SPA с webapi реализовано через Asp.net ядро. Я видел статью - Как реализовать ее с помощью EF Identity, но их модели выглядят намного сложнее, чем мне на самом деле нужно, и EF ориентирован на SQL db, и я использую mongo. Поэтому мой пользователь будет выглядеть примерно так:
class UserModel{
Id,
Token,
Roles: ["Owners", "Users"],
...
}
Итак, какие интерфейсы мне нужно реализовать и добавить DI, чтобы иметь возможность использовать
[Authorize]
и [Authorize(Roles="Users")]
атрибут и они работали правильно на основе токена, который я отправляю в заголовок?
2 ответов
позвольте мне уточнить немного ответ @Adem. Вам нужно реализовать пользовательское промежуточное по определенным образом. Существует 3 абстрактных класса, которые необходимо реализовать для реализации этого (Ответ правильный для asp.net core rc2
btw):
Microsoft.AspNetCore.Builder.AuthenticationOptions
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware<TOptions>
Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions>
а затем добавьте это промежуточное ПО в свой класс запуска.
пример кода:
public class TokenOptions : AuthenticationOptions
{
public TokenOptions() : base()
{
AuthenticationScheme = "Bearer";
AutomaticAuthenticate = true;
}
}
public class AuthMiddleware : AuthenticationMiddleware<TokenOptions>
{
protected override AuthenticationHandler<TokenOptions> CreateHandler()
{
return new AuthHandler(new TokenService());
}
public AuthMiddleware(RequestDelegate next, IOptions<TokenOptions> options, ILoggerFactory loggerFactory, UrlEncoder encoder) : base(next, options, loggerFactory, encoder)
{
}
}
public class AuthHandler : AuthenticationHandler<TokenOptions>
{
private ITokenService _tokenService;
public AuthHandler(ITokenService tokenService)
{
_tokenService = tokenService;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
string token = null;
AuthenticateResult result = null;
string token = Helper.GetTokenFromHEader(Request.Headers["Authorization"]);
// If no token found, no further work possible
if (string.IsNullOrEmpty(token))
{
result = AuthenticateResult.Skip();
}
else
{
bool isValid = await _tokenService.IsValidAsync(token);
if (isValid)
{
//assigning fake identity, just for illustration
ClaimsIdentity claimsIdentity = new ClaimsIdentity("Custom");
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, "admin"));
claims.Add(new Claim(ClaimTypes.NameIdentifier, "admin"));
claims.Add(new Claim(ClaimTypes.Role, "admin"));
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
result =
AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal,
new AuthenticationProperties(), Options.AuthenticationScheme));
}
else
{
result = AuthenticateResult.Skip();
}
}
return result;
}
}`
p.s. Код просто для иллюстрации идеи. Вам нужно будет реализовать свой собственный обработчик конечно.
вы можете использовать custom middleware
для аутентификации пользователя и установки claims
(наименование, функции и т. д.).
Я постараюсь написать просто middleware
:
создать middlware
class
:
public class CustomMiddleware
{
private readonly RequestDelegate _next;
private readonly UserRepository _userRepository;
public CustomMiddleware(RequestDelegate next, UserRepository userRepository)
{
_next = next;
_userRepository = userRepository;
}
public async Task Invoke(HttpContext context)
{
string token = context.Request.Headers["Token"];
var user = _userRepository.Get(token);
ClaimsIdentity claimsIdentity = new ClaimsIdentity("Custom");
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, "admin"));
claims.Add(new Claim(ClaimTypes.NameIdentifier, "admin"));
foreach(var role in user.Roles)
{
claims.Add(ClaimTypes.Role, role);
}
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
context.User = claimsPrincipal;
await _next(context);
}
}
затем использовать middleware
на Startup.cs
такой:
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<CustomMiddleware>();
...
}
и :
[Authorize(Roles = "Users")]
public IActionResult Index()
{
}