Есть ли способ свободно соединить этот базовый фильтр аутентификации - PullRequest
0 голосов
/ 12 июня 2019

У меня есть веб-интерфейс asp.net, и я хотел бы использовать базовую аутентификацию. Есть ли способ сделать это слабосвязанным? Я пробовал конструктор 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:

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();


        }        
    }
}

Edit: Я попытался реализовать провайдера следующим образом на основе решения 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)
            };
        }
    }

А это привязка к нинъекту:

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

Но обычная аутентификация не срабатывает.

1 Ответ

0 голосов
/ 12 июня 2019

refactor UserValidate

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();
}

вы разрешите атрибут в конфигурации и добавите его в фильтры

public static class WebApiConfig {
    public static void Register(HttpConfiguration config) {

        var resolver = config.DependencyResolver; //Assuming one is set.
        var basicAuth = resolver.GetService(typeof(BasicAuthenticationAttribute)) as BasicAuthenticationAttribute;
        // Web API configuration and services
        config.Filters.Add(basicAuth);

        //...omitted for brevity
...