C # Отправить информацию о входе в JSON в теле и получить аутентификацию Web API Оуэн не работает - PullRequest
0 голосов
/ 14 октября 2019

Я пытаюсь создать сервер веб-API с аутентификацией, используя Owin и связанные с ним вещи. Проблема в том, что мой разработчик внешнего интерфейса отправит в виде JSON текст сообщения электронной почты и пароль для проверки подлинности. Пожалуйста, помогите мне, где я не прав, сообщение всегда

{
    "Message": "Authorization has been denied for this request."
}

Вот мой запрос на вход в LoginController.cs

[HttpPost]
        [Authorize]
        [Route("token/reg/signin")]
        public async Task<HttpResponseMessage> SubmitSignIn([FromBody]object data)
        {
            //Convert data receive to json string
            string json = JsonConvert.SerializeObject(data);
            Debug.WriteLine("Receive value:" + json);

            //Initial user registration info and convert json string to class
            DefStruct.LoginInfo logInfo = new DefStruct.LoginInfo();
            logInfo = JsonConvert.DeserializeObject<DefStruct.LoginInfo>(json);

            //Check the connection state with DB
            if (SQLConnection.Instance.Conn.State != ConnectionState.Open)
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, DefString.DATABASE_ERROR);

            //Check user register email available or not
            bool isAvailable = await RegQuery.CheckEmail(logInfo.Email);
            if (isAvailable)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, DefString.EMAIL_NOT_EXIST);

            //Check email and password is validate or not
            bool isValidate = await RegQuery.ValidateUser(logInfo.Email, logInfo.Password);
            if (!isValidate)
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, DefString.WRONG_EMAIL_PASSWORD);

            return Request.CreateResponse(HttpStatusCode.OK, "Login sucess");
        }

Вот мой Startup.cs

 public class Startup
    {
        public static Startup Instance { get; private set; }

        public OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
        public OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }
        public void ConfigureAuth(IAppBuilder app)
        {
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                Provider = new ApplicationAuthorizationProvider()
            };

            OAuthBearerOptions = new OAuthBearerAuthenticationOptions();

            app.UseOAuthBearerTokens(OAuthOptions);
            app.UseOAuthAuthorizationServer(OAuthOptions);
            app.UseOAuthBearerAuthentication(OAuthBearerOptions);

            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config);
            app.UseWebApi(config);
        }

        public void Configuration(IAppBuilder app)
        {
            //Default configuration
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            //Custom configuration
            DataSourceConfig.ConnectDatabase();
            ModulesConfig.InitialAllModules();

            //Authentication configuration
            ConfigureAuth(app);

            Instance = this;
        }

        public string GetToken(AuthenticationTicket ticketData)
        {
            string token;
            token = OAuthBearerOptions.AccessTokenFormat.Protect(ticketData);
            return token;
        }
    }

Вот ApplicationAuthorizationProvider.cs

 public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            //Read the position to the end
            context.Request.Body.Position = 0;

            //Convert to json string
            var payload = await new StreamReader(context.Request.Body).ReadToEndAsync();

            //Parse json string
            DefStruct.LoginInfo logInfo = JsonConvert.DeserializeObject<DefStruct.LoginInfo>(payload);

            context.OwinContext.Set<string>("email", logInfo.Email);
            context.OwinContext.Set<string>("password", logInfo.Password);

            context.Validated();   
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            var email = context.OwinContext.Get<string>("email");
            var password = context.OwinContext.Get<string>("password");

            var user = await RegQuery.ValidateUser(email, password);
            if(user)
            {
                var claim = new Claim(ClaimTypes.Email, email);
                var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
                oAuthIdentity.AddClaim(claim);
                var properties = Authentication.CreateProperties(email);
                var ticket = new AuthenticationTicket(oAuthIdentity, properties);
                context.Validated(ticket);
            }
            else
            {
                context.SetError("invalid_grant", "The email or password is incorrect.");
            }
        }

Есть 3 вещи, которые я до сих пор путаю:

  1. Почему запрос token/reg/signin никогда не запускается ValidateClientAuthentication и GrantResourceOwnerCredentials ? Кто-нибудь может объяснить причину?

  2. Если я хочу создать токен вручную, я вызывал этот код из своего класса Authentication.cs , который GetToken inside Startup.cs и accessToken всегда возвращают ноль. Почему?

public static string GenerateToken(string email)
       {
           string accessToken;

           var claim = new Claim(ClaimTypes.Email, email);
           var oAuthIdentity = new ClaimsIdentity();
           oAuthIdentity.AddClaim(claim);

           var properties = CreateProperties(email);
           var ticket = new AuthenticationTicket(oAuthIdentity, properties);
           accessToken = Startup.Instance.GetToken(ticket);
           return accessToken;
       }

       public static AuthenticationProperties CreateProperties(string email)
       {
           IDictionary<string, string> data = new Dictionary<string, string>
           {
               { "email", email }
           };
           return new AuthenticationProperties(data);
       }
Так что вообще не так, мои идеи просты: клиент отправляет запрос в виде JSON -> сервер читает -> проверен -> генерирует токен и отправляет ответ с дополнительным ответом на данные, но это уже занимает несколько дней с огромным поиском в Google,Может быть, мой вопрос настолько глуп, что кто-то уже сделал это, но, пожалуйста, помогите мне разобраться
...