有没有一种方法可以松散耦合此基本身份验证筛选器

时间:2019-06-12 10:05:25

标签: c# asp.net-web-api dependency-injection ninject

我有一个asp.net网络api,我想使用基本身份验证。有什么办法可以使这种松散耦合吗?我尝试了构造函数DI,但无法弄清楚如何将Dbcontext传递到WebApiConfig。任何帮助将不胜感激。

这是我的界面:

public interface IUserValidate
    {
        bool Login(string username, string password);
    }

这是我的课程:

public class UserValidate : IUserValidate
    {

        //This method is used to check the user credentials
        public bool Login(string username, string password)
        {
            using (var context = new EPINMiddleWareAPIContext())
            {
                return context.Companies.Any(user =>
                    user.userName.Equals(username, StringComparison.OrdinalIgnoreCase)
                    && user.password == password);
            }

        }
    }

这是我的基本身份验证过滤器:

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
    {

        private const string Realm = "My Realm";


        public override void OnAuthorization(HttpActionContext actionContext)
        {
            //If the Authorization header is empty or null
            //then return Unauthorized
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request
                    .CreateResponse(HttpStatusCode.Unauthorized);
                // If the request was unauthorized, add the WWW-Authenticate header 
                // to the response which indicates that it require basic authentication
                if (actionContext.Response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    actionContext.Response.Headers.Add("WWW-Authenticate",
                        string.Format("Basic realm=\"{0}\"", Realm));
                }
            }
            else
            {
                //Get the authentication token from the request header
                string authenticationToken = actionContext.Request.Headers
                    .Authorization.Parameter;
                //Decode the string
                string decodedAuthenticationToken = Encoding.UTF8.GetString(
                    Convert.FromBase64String(authenticationToken));
                //Convert the string into an string array
                string[] usernamePasswordArray = decodedAuthenticationToken.Split(':');
                //First element of the array is the username
                string username = usernamePasswordArray[0];
                //Second element of the array is the password
                string password = usernamePasswordArray[1];
                //call the login method to check the username and password
                UserValidate uv = new UserValidate();
                if (uv.Login(username, password))
                {
                    var identity = new GenericIdentity(username);
                    IPrincipal principal = new GenericPrincipal(identity, null);
                    Thread.CurrentPrincipal = principal;
                    if (HttpContext.Current != null)
                    {
                        HttpContext.Current.User = principal;
                    }
                }
                else
                {
                    actionContext.Response = actionContext.Request
                        .CreateResponse(HttpStatusCode.Unauthorized);
                }
            }
        }

    }

这是我的WebApiConfig:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            config.Filters.Add(new BasicAuthenticationAttribute());
            // Web API routes
            config.MapHttpAttributeRoutes();
            //Registering GlobalExceptionHandler
            config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
            //Registering UnhandledExceptionLogger
            config.Services.Replace(typeof(IExceptionLogger), new UnhandledExceptionLogger());
            //Registering RequestResponseHandler
            config.MessageHandlers.Add(new RequestResponseHandler());
            //Validate Token
            //config.MessageHandlers.Add(new TokenValidationHandler());

            //Registering CustomExceptionFilter
            config.Filters.Add(new CustomExceptionFilter());

        }
    }

这是我的Dbcontext:

public class EPINMiddleWareAPIContext : DbContext
    {

        public EPINMiddleWareAPIContext() : base("name=EPINMiddleWareAPIContext")
        {
        }

        public DbSet<InitiateRequest> InitiateRequests { get; set; }
        public DbSet<InitiateResponse> InitiateResponses { get; set; }
        public DbSet<Company> Companies { get; set; }
        public DbSet<ConfirmRequest> ConfirmRequests { get; set; }
        public DbSet<ConfirmResponse> ConfirmResponses { get; set; }
        public DbSet<GameBank> GameBanks { get; set; }
        public DbSet<GameCouponBank> GameCouponBanks { get; set; }

    }

这是我的Ninject Web Common:

using EPINMiddleWareAPI.Controllers;

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(EPINMiddleWareAPI.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(EPINMiddleWareAPI.App_Start.NinjectWebCommon), "Stop")]

namespace EPINMiddleWareAPI.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;
    using Models;
    using Ninject.Web.Common.WebHost;

    public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start() 
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<EPINMiddleWareAPIContext>().ToSelf().InRequestScope();


        }        
    }
}

编辑: 我尝试根据Nkosi的解决方案来实现提供者,如下所示:

public class AuthenticationFilterProvider : System.Web.Http.Filters.IFilterProvider
    {
        private readonly Func<BasicAuthenticationAttribute> _authorizeViewFilterFactory;

        public AuthenticationFilterProvider(Func<BasicAuthenticationAttribute> authorizeViewFilterFactory)
        {
            this._authorizeViewFilterFactory = authorizeViewFilterFactory;
        }

        public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
        {
            if (!actionDescriptor.GetCustomAttributes<BasicAuthenticationAttribute>().Any())
                return Enumerable.Empty<FilterInfo>();

            return new[]
            {
                new FilterInfo(this._authorizeViewFilterFactory(), FilterScope.Action)
            };
        }
    }

与ninject绑定:

kernel.Bind<System.Web.Http.Filters.IFilterProvider>().To<AuthenticationFilterProvider>();

但是基本身份验证未触发。

1 个答案:

答案 0 :(得分:0)

重构 UserValidate

        #the following code is in java. This class imitates the Json Object and follows it's hierarchy
        public class MyPojo
        {


            private String code;

            private String lastActive;

            private PrimaryContactExpanded primaryContactExpanded;

            private PrimaryContact primaryContact;

            private String id;

            private Status status;

            public String getCode ()
            {
                return code;
            }

            public void setCode (String code)
            {
                this.code = code;
            }

            public String getLastActive ()
            {
                return lastActive;
            }

            public void setLastActive (String lastActive)
            {
                this.lastActive = lastActive;
            }

            public PrimaryContactExpanded getPrimaryContactExpanded ()
            {
                return primaryContactExpanded;
            }

            public void setPrimaryContactExpanded (PrimaryContactExpanded primaryContactExpanded)
            {
                this.primaryContactExpanded = primaryContactExpanded;
            }

            public PrimaryContact getPrimaryContact ()
            {
                return primaryContact;
            }

            public void setPrimaryContact (PrimaryContact primaryContact)
            {
                this.primaryContact = primaryContact;
            }

            public String getId ()
            {
                return id;
            }

            public void setId (String id)
            {
                this.id = id;
            }

            public Status getStatus ()
            {
                return status;
            }

            public void setStatus (Status status)
            {
                this.status = status;
            }


        //In order to deserialize it and fetch it through a list I have used the following code


    List<MyPojo> customers = response.jsonPath().getList(".", MyPojo.class);

                //System.out.println(response.jsonPath().get("primaryContactExpanded.companyName"));
                for(MyPojo customer : customers)
         {
                    System.out.println(customer.getId());
                    System.out.println(customer.getPrimaryContactExpanded().getDisplayAs());
                }

It performs the deserialization of an json object into a list of MyPojo class
And I can fetch the values while iterating it through the list 
        How can I perform the same for IRestSharp response and deserialize it into a list of List of a class object and for each iteration fetch the values

    I am not able to perform the same task in C#.

如果您不打算使用该属性来装饰任何东西,而只打算在config中使用它,则可以将其重构为使用带有工厂的构造函数注入以获取服务。

public class UserValidate : IUserValidate {
    private EPINMiddleWareAPIContext context;

    public UserValidate(EPINMiddleWareAPIContext context) {
        this.context = context;
    }

    //This method is used to check the user credentials
    public bool Login(string username, string password) {
        return context.Companies.Any(user =>
            user.userName.Equals(username, StringComparison.OrdinalIgnoreCase)
            && user.password == password
        );
    }
}

相应地注册您的服务

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute {

    private const string Realm = "My Realm";
    readonly Func<IUserValidate> factory;

    public BasicAuthenticationAttribute(Func<IUserValidate> factory) {
        this.factory = factory;
    }

    public override void OnAuthorization(HttpActionContext actionContext) {
        //If the Authorization header is empty or null
        //then return Unauthorized
        if (actionContext.Request.Headers.Authorization == null) {
            actionContext.Response = actionContext.Request
                .CreateResponse(HttpStatusCode.Unauthorized);
            // If the request was unauthorized, add the WWW-Authenticate header 
            // to the response which indicates that it require basic authentication
            if (actionContext.Response.StatusCode == HttpStatusCode.Unauthorized) {
                actionContext.Response.Headers.Add("WWW-Authenticate",
                    string.Format("Basic realm=\"{0}\"", Realm));
            }
        } else {
            //Get the authentication token from the request header
            string authenticationToken = actionContext.Request.Headers
                .Authorization.Parameter;
            //Decode the string
            string decodedAuthenticationToken = Encoding.UTF8.GetString(
                Convert.FromBase64String(authenticationToken));
            //Convert the string into an string array
            string[] usernamePasswordArray = decodedAuthenticationToken.Split(':');
            //First element of the array is the username
            string username = usernamePasswordArray[0];
            //Second element of the array is the password
            string password = usernamePasswordArray[1];
            //call the login method to check the username and password
            IUserValidate uv = factory(); 
            if (uv.Login(username, password)) {
                var identity = new GenericIdentity(username);
                IPrincipal principal = new GenericPrincipal(identity, null);
                Thread.CurrentPrincipal = principal;
                if (HttpContext.Current != null) {
                    HttpContext.Current.User = principal;
                }
            } else {
                actionContext.Response = actionContext.Request
                    .CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
    }
}

您解析配置中的属性并将其添加到过滤器

private static void RegisterServices(IKernel kernel) {
    kernel.Bind<EPINMiddleWareAPIContext>().ToSelf().InRequestScope();
    kernel.Bind<IUserValidate>().To<UserValidate>();
    kernel.Bind<BasicAuthenticationAttribute>().ToSelf();
}