如何使用网络中的过滤器传递带有错误消息的状态 api

how to pass the status with error message using Filters in web api

我不知道我在哪里失踪如果用户名和密码错误,我会被卡住发送错误消息。我的服务运行良好,如果用户 ID 和密码与 200 状态不匹配并且手动创建的状态成功,我可以手动发送错误消息。这是我创建的代码 HandleRequest class

public class HandleRequest : Attribute, IAuthenticationFilter
    {
        public string Realm { get; set; }




        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            //throw new NotImplementedException();
            HttpRequestMessage request = context.Request;
            AuthenticationHeaderValue authorization = request.Headers.Authorization;

            string status = await SendAsync(request, cancellationToken);


            if (context.Request.RequestUri.LocalPath == "/Login/UserLogin")
            {
                return;
            }
            else if (authorization == null)
            {
                // No authentication was attempted (for this authentication method).
                // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error).
                context.ErrorResult = new AuthenticationFailureResult("Null auth token..", request);
                return;
            }
            else if (status == "Success")
            {
                return;
            }
            else
            {
                context.ErrorResult = new AuthenticationFailureResult("Invalid auth token..", request);
                return;
            }
        }


        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            Challenge(context);
            return Task.FromResult(0);
        }

        private void Challenge(HttpAuthenticationChallengeContext context)
        {
            string parameter;

            if (String.IsNullOrEmpty(Realm))
            {
                parameter = null;
            }
            else
            {
                // A correct implementation should verify that Realm does not contain a quote character unless properly
                // escaped (precededed by a backslash that is not itself escaped).
                parameter = "realm=\"" + Realm + "\"";
            }

            context.ChallengeWith("Basic", parameter);
        }

        public virtual bool AllowMultiple
        {
            get { return false; }
        }




        private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
        {
            token = null;
            IEnumerable<string> authzHeaders;
            if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
            {
                return false;
            }
            var bearerToken = authzHeaders.ElementAt(0);
            token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
            return true;
        }

        public async Task<string> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            string status = "";
            HttpStatusCode statusCode;
            string token;
            //determine whether a jwt exists or not
            if (!TryRetrieveToken(request, out token))
            {
                statusCode = HttpStatusCode.Unauthorized;
                //allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
                //return base.SendAsync(request, cancellationToken);
            }

            try
            {
                string sec = WebConfigurationManager.AppSettings["sec"];
                var now = DateTime.UtcNow;
                var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));


                SecurityToken securityToken;
                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                TokenValidationParameters validationParameters = new TokenValidationParameters()
                {
                    ValidAudience = "http://localhost:1987",
                    ValidIssuer = "http://localhost:1987",
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    LifetimeValidator = this.LifetimeValidator,
                    IssuerSigningKey = securityKey
                };
                //extract and assign the user of the jwt
                Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
                HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);


                var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;


                var id = int.Parse(identity.Claims.Where(c => c.Type == "id")
                  .Select(c => c.Value).SingleOrDefault());


                bool isValidToken = IsValidToken(id, userName, type);
                if (isValidToken == true)
                {
                    status = "Success";
                }
                else
                {
                    statusCode = HttpStatusCode.Unauthorized;
                    status = "Unauthorized";
                }

            }
            catch (SecurityTokenValidationException e)
            {
                e.Message.ToString();
                statusCode = HttpStatusCode.Unauthorized;
                status = "Unauthorized";
            }
            catch (Exception ex)
            {
                ex.Message.ToString();
                statusCode = HttpStatusCode.InternalServerError;
                status = "InternalServerError";
            }

            return status;
        }
        public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
        {
            if (expires != null)
            {
                if (DateTime.UtcNow < expires) return true;
            }
            return false;
        }

        private bool IsValidToken(int? id, string userName, string type)
        {
            bool isValid = false;
            using (MCSDEMOEntities con = new MCSDEMOEntities())
            {
                var GetUserDatails = (from u in con.ios_Users
                                      where u.ID == id && u.LOGIN == userName && u.TYPEDESCR == type
                                      select u).ToList();
                if (GetUserDatails.Count == 1)
                {
                    isValid = true;
                }
                else
                {
                    isValid = false;
                }
            }

            return isValid;
        }


    }





    public static class HttpRequestHeadersExtensions
    {
        public static void Set(this HttpRequestHeaders headers, string name, string value)
        {
            if (headers.Contains(name)) headers.Remove(name);
            headers.Add(name, value);
        }
    }

    public static class HttpAuthenticationChallengeContextExtensions
    {
        public static void ChallengeWith(this HttpAuthenticationChallengeContext context, string scheme)
        {
            ChallengeWith(context, new AuthenticationHeaderValue(scheme));
        }

        public static void ChallengeWith(this HttpAuthenticationChallengeContext context, string scheme, string parameter)
        {
            ChallengeWith(context, new AuthenticationHeaderValue(scheme, parameter));
        }

        public static void ChallengeWith(this HttpAuthenticationChallengeContext context, AuthenticationHeaderValue challenge)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
        }
    }


    public class AddChallengeOnUnauthorizedResult : IHttpActionResult
    {
        public AuthenticationHeaderValue Challenge { get; private set; }
        public IHttpActionResult InnerHttpResult { get; private set; }

        public AddChallengeOnUnauthorizedResult(AuthenticationHeaderValue challenge, IHttpActionResult innerResult)
        {
            Challenge = challenge;
            InnerHttpResult = innerResult;
        }

        public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = await InnerHttpResult.ExecuteAsync(cancellationToken);

            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                // Only add one challenge per authentication scheme.
                if (!response.Headers.WwwAuthenticate.Any((h) => h.Scheme == Challenge.Scheme))
                {
                    response.Headers.WwwAuthenticate.Add(Challenge);
                }
            }

            return response;
        }
    }

    public class AuthenticationFailureResult : IHttpActionResult
    {
        public string ReasonPhrase { get; private set; }
        public HttpRequestMessage Request { get; private set; }

        public AuthenticationFailureResult(string reasonPhrase, HttpRequestMessage request)
        {
            ReasonPhrase = reasonPhrase;
            Request = request;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(execute());
        }

        private HttpResponseMessage execute()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            response.RequestMessage = Request;
            response.ReasonPhrase = ReasonPhrase;
            return response;
        }
    }

我的webapi config file

  public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
           config.MapHttpAttributeRoutes();

            //check each request
            config.Filters.Add(new HandleRequest());

            // configuration for json reponse
            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

            //LoginController
            // Login Model

            config.Routes.MapHttpRoute(
               name: "LoginApi",
               routeTemplate: "{controller}/{action}",
               defaults: new { controller = "Login", action = "UserLogin", id = RouteParameter.Optional }
            );
}

和我的登录控制器

  public class LoginController : ApiController
    {
        LoginModel logMod = new LoginModel();
        LoginResponse logResp = new LoginResponse();


        [HttpPost]
        public  LoginResponse UserLogin(LoginRequest logReq)
        {
            logResp = logMod.UserLogin(logReq );
            return logResp;
        }
    }

登录模式class

        public  LoginResponse UserLogin(LoginRequest LogReq)
        {

            LoginResponse logResp = new LoginResponse();
            try
            {
                if (LogReq.userName != "" && LogReq.password != "")
                {
                    using (MCSDEMOEntities DataModel = new MCSDEMOEntities())
                    {
                        var UserDetails = (from user in DataModel.ios_Users
                                           where (user.LOGIN == LogReq.userName && user.PASSWORD == LogReq.password && user.ACTIVE != 0)
                                           select new
                                           {
                                               user.ID,
                                               user.TYPEDESCR,
                                               user.USERNAME
                                           }).ToList();
                        if (UserDetails.Count != 0)
                        {
                            foreach (var Udetails in UserDetails)
                            {
                                logResp.id = Udetails.ID;
                                logResp.type = Udetails.TYPEDESCR;
                                logResp.userName = Udetails.USERNAME;
                            }
                            //create jwt token.
                            logResp.userToken = createToken(logResp.id, logResp.type, LogReq.userName);
                            logResp.Status = "Success";
                        }
                        else
                        {
                            logResp.Status = "401";
                            //throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest);
                          // throw new AuthenticationFailureResult("","")
                        }
                    }
                }
                else
                {
                    logResp.Status = "No Condition Match";
                }

            }
            catch (Exception ex)
            {
                logResp.Status = ex.Message.ToString();
            }

            return logResp;
        }

在上面的代码中,它很好地执行了服务,但即使用户 ID 和密码不匹配,它也会发送 http-200 ok 消息和我的状态 - json 中的 401。我想通过代码 401

传递 http

您需要 return HttpResponseMessage 来自您的 api 以便您可以使用状态等其他信息包装您的响应对象

    [HttpPost]
    public  HttpResponseMessage UserLogin(LoginRequest logReq)
    {
        logResp = logMod.UserLogin(logReq );
        // Decide based on your logic. This is
        // a mock example. 
        var status = HttpStatusCode.OK
        return Request.CreateResponse(HttpStatusCode.OK, logResp);
    }

您可以在此处找到更多信息:https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/action-results

引自:

HttpResponseMessage Convert directly to an HTTP response

Other type Write the serialized return value into the response body; return 200 (OK).