TokenEndPoint не найден при аутентификации пользователя из SPA в Web API с использованием OWIN
Я сталкиваюсь с трудностями при аутентификации пользователей с использованием механизма токенов от Angular JS SPA Page до WEB API.
Я не хочу использовать таблицы по умолчанию удостоверений ASP.NET для добавления или аутентификации пользователя. У меня есть собственная база данных и таблица с именем "EmployeeAccess", которая содержит EmployeeNumber в качестве идентификатора пользователя и пароля. Я хочу аутентифицировать пользователей по значениям в этой таблице, а затем хочу предоставить токен, чтобы они авторизовались для последующего вызова. Я использовал все необходимые ссылки OWIN и ASP.NET для достижения результата.
Пожалуйста, смотрите соответствующий код ниже:-
Startup.cs
[assembly: OwinStartup(typeof(Application.WebAPI.Startup))]
namespace Application.WebAPI
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var myProvider = new AuthorizationServerProvider();
OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/Token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = myProvider
};
app.UseOAuthAuthorizationServer(options);
}
}
}
AuthorizationServerProvider.cs
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated(); //
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
string userId = context.UserName;
string password = context.Password;
EmployeeAccessBLL chkEmpAccessBLL = new EmployeeAccessBLL();
EmployeeAccessViewModel vmEmployeeAccess = chkEmpAccessBLL.CheckEmployeeAccess(Convert.ToInt32(userId), password);
if(vmEmployeeAccess != null)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("username", vmEmployeeAccess.EmpName));
context.Validated(identity);
}
else
{
context.SetError("invalid_grant", "Provided username and password is incorrect");
return;
}
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.Formatters.Remove(config.Formatters.XmlFormatter);
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
}
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<script src="../Scripts/AngularControllers/LoginController.js"></script>
<script src="../Scripts/AngularServices/ApiCallService.js"></script>
</head>
<body ng-app="appHome">
<div ng-controller="ctrlLogin">
<label>Employee Number</label>
<input type="text" id="txtEmpNumber" ng-model="md_empnumber" />
<br/>
<br/>
<label>Password</label>
<input type="text" id="txtEmpNumber" ng-model="md_password" />
<button id="btnAdd" type="submit" ng-click="Login()">Login</button>
</div>
</body>
</html>
LoginController.js
var myApp = angular.module('appHome', []);
myApp.controller("ctrlLogin", ['$scope', 'MetadataOrgFactory', '$location', function ($scope, MetadataOrgFactory, $location) {
$scope.Login = function () {
var objLogin = {
'username' : $scope.md_empnumber,
'password' : $scope.md_password,
'grant_type' : 'password'
};
MetadataOrgFactory.postLoginCall('Token', objLogin, function (dataSuccess) {
alert("Welcome " + dataSuccess);
}, function (dataError) {
});
}
}]);
ApiCallService.js
var appService = angular.module('appHome');
appService.factory('MetadataOrgFactory', ['$http', function ($http) {
var url = 'http://localhost:60544';
var dataFactory = {};
dataFactory.postLoginCall = function (controllerName, objData, callbackSuccess, callbackError) {
$http.post(url + '/' + controllerName, objData).then
(function success(response) {
alert("Success");
callbackSuccess(response.data);
}, function error(response) {
callbackError(response.status);
});
};
return dataFactory;
}])
Я получаю следующие две ошибки, когда нажимаю кнопку входа в систему:-
ОПЦИИ http://localhost:60544/Token 404 (не найден)
XMLHttpRequest не может загрузить http://localhost:60544/Token. Ответ на запрос предварительной проверки не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок "Access-Control-Allow-Origin". Поэтому происхождение ' http://localhost:60512/' не разрешено. Ответ имел HTTP-код состояния 404.
Я искал много сообщений, но ни одно из них не соответствовало моим критериям, поэтому подумал о том, чтобы опубликовать свой запрос. Пожалуйста, помогите мне в этом.
1 ответ
Ошибка является результатом вызова OPTIONS.
Метод HTTP OPTIONS используется для описания параметров связи для целевого ресурса. Клиент может указать конкретный URL-адрес для метода OPTIONS или звездочку (*) для ссылки на весь сервер.
Поскольку вы не обрабатываете их, вы увидите 404 (не найдено). Вы можете прочитать о CORS здесь: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Одним из способов реализации этого является добавление в Global.asax следующего кода:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
// Cache the options request.
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", HttpContext.Current.Request.Headers["Origin"]);
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, PUT, DELETE, POST, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
}