Аутентификация на основе токенов в Web API без пользовательского интерфейса
Я занимаюсь разработкой API-интерфейс REST в Интернете ASP.Net API-интерфейс. Мой API будет доступно только через браузер, клиенты. Мне нужно реализовать безопасность для моего API, поэтому я решил пойти с аутентификацией на основе токенов. Я хорошо понимаю аутентификацию на основе токенов и прочитал несколько руководств, но у всех есть пользовательский интерфейс для входа. Мне не нужен пользовательский интерфейс для входа в систему, поскольку данные для входа будут переданы клиентом через HTTP POST, который будет авторизован из нашей базы данных. Как могу ли я реализовать аутентификацию на основе токенов в моем API? Обратите внимание - мой API будет доступно на высокой частоте, поэтому я также должен заботиться о производительности. Пожалуйста, дайте мне знать, если я смогу объяснить это лучше.
2 ответов
Я думаю, что существует некоторая путаница в отношении разницы между MVC и Web Api. Короче говоря, для MVC вы можете использовать форму входа в систему и создать сеанс с помощью cookies. Для Web Api нет сеанса. Вот почему вы хотите использовать маркер.
вам не нужна форма входа. Конечная точка токена-это все, что вам нужно. Как описано в Win, вы отправите учетные данные в конечную точку токена, где она обрабатывается.
вот некоторый клиентский код C# для получения токен:
//using System;
//using System.Collections.Generic;
//using System.Net;
//using System.Net.Http;
//string token = GetToken("https://localhost:<port>/", userName, password);
static string GetToken(string url, string userName, string password) {
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password" ),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "Password", password )
};
var content = new FormUrlEncodedContent(pairs);
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient()) {
var response = client.PostAsync(url + "Token", content).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
чтобы использовать токен, добавьте его в заголовок запроса:
//using System;
//using System.Collections.Generic;
//using System.Net;
//using System.Net.Http;
//var result = CallApi("https://localhost:<port>/something", token);
static string CallApi(string url, string token) {
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient()) {
if (!string.IsNullOrWhiteSpace(token)) {
var t = JsonConvert.DeserializeObject<Token>(token);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + t.access_token);
}
var response = client.GetAsync(url).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
где знак-это:
//using Newtonsoft.Json;
class Token
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string userName { get; set; }
[JsonProperty(".issued")]
public string issued { get; set; }
[JsonProperty(".expires")]
public string expires { get; set; }
}
теперь для стороны сервера:
В Автозагрузку.Автор.cs
var oAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider("self"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// https
AllowInsecureHttp = false
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(oAuthOptions);
и в ApplicationOAuthProvider.cs код, который фактически предоставляет или запрещает доступ:
//using Microsoft.AspNet.Identity.Owin;
//using Microsoft.Owin.Security;
//using Microsoft.Owin.Security.OAuth;
//using System;
//using System.Collections.Generic;
//using System.Security.Claims;
//using System.Threading.Tasks;
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private readonly string _publicClientId;
public ApplicationOAuthProvider(string publicClientId)
{
if (publicClientId == null)
throw new ArgumentNullException("publicClientId");
_publicClientId = publicClientId;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
var user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager);
var propertyDictionary = new Dictionary<string, string> { { "userName", user.UserName } };
var properties = new AuthenticationProperties(propertyDictionary);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
// Token is validated.
context.Validated(ticket);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
context.Validated();
return Task.FromResult<object>(null);
}
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
var expectedRootUri = new Uri(context.Request.Uri, "/");
if (expectedRootUri.AbsoluteUri == context.RedirectUri)
context.Validated();
}
return Task.FromResult<object>(null);
}
}
как вы можете видеть, нет контроллера, участвующего в получении токена. Фактически, вы можете удалить все ссылки MVC, если хотите веб-сайт Только Api. Я упростил код на стороне сервера, чтобы сделать его более читабельным. Вы можете добавить код для повышения безопасности.
убедитесь, что вы используете только SSL. Осуществлять RequireHttpsAttribute к этой силе.
для защиты веб-Api можно использовать атрибуты Authorize / AllowAnonymous. Кроме того, вы можете добавить фильтры (например, RequireHttpsAttribute), чтобы сделать ваш веб-Api более безопасным. Надеюсь, это поможет.
ASP.Net Web API уже имеет встроенный сервер авторизации. вы можете увидеть его внутри Автозагрузка.cs при создании нового ASP.Net веб-приложение с шаблоном Web API.
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
все, что вам нужно сделать, это разместить url-кодированное имя пользователя и пароль внутри строки запроса.
/Token/userName=johndoe%40example.com&password=1234&grant_type=password
Если вы хотите знать больше детали, вы можете смотреть регистрация пользователя и логин-угловой фронт к спине с веб-API Дебора Курата!--13-->.