Ajax Вызов веб-API с проверкой подлинности с помощью форм - PullRequest
0 голосов
/ 09 мая 2020

Мы работали над веб-приложением asp. net и реализовали в нем проверку подлинности с помощью форм. В последнее время у нас появились требования предоставить некоторые функции приложения для других систем. Поэтому мы планируем разработать веб-API для этого приложения. Нам нужно разместить эти веб-API в одном веб-приложении IIS, и нам нужно сделать их безопасными. Поэтому я добавил атрибут [Authorize] в класс контроллера веб-API.

Теперь я не совсем понимаю, что такое его безопасность. Если мы сохраним аутентификацию с помощью форм, то как я могу аутентифицировать свои внешние системные вызовы? Или мне нужно использовать какой-либо другой механизм аутентификации (например, OAuth), но будет ли он работать в том же приложении, где у нас есть аутентификация с помощью форм? Я также включаю COR в классе контроллера API. Путаница касается только механизма безопасности.

У нас есть приложение angular и собственное мобильное приложение для использования этих API. Angular Приложение размещается отдельно в IIS, а мобильное приложение работает на IOS и Android.

Пожалуйста, предложите решение, поскольку я не уверен, в каком направлении мне следует двигаться.

С уважением, Джамиль

1 Ответ

0 голосов
/ 13 мая 2020

Я следую этой статье Смешивание MVC + Проверка подлинности веб-API (с использованием форм Auth + Basi c Auth) .

Короче говоря, для внешних систем для аутентификации в WebAPI нельзя использовать Forms Auth, мы должны использовать Basi c Auth или OAuth. OAuth нельзя смешивать с Form Auth, если все приложение не обновлено для использования OAuth, но, определив SecurityFilter для веб-API, мы можем поддерживать работу проверки подлинности с помощью форм в веб-приложении и параллельно с этим мы можем определить Basi c Authentication Безопасность, которая будет использовать Basi c Authentication или любой другой механизм аутентификации, который мы можем использовать.

Для меня это решение работает.

  1. Я создаю контроллер веб-API в Интернете form project.
  2. По умолчанию, поскольку проверка подлинности с помощью форм включена на уровне всего сайта с помощью Web.Config. Этот новый контроллер также защищен с помощью проверки подлинности с помощью форм. Чтобы пропустить эту безопасность, я добавил тег местоположения в веб-конфигурацию и разрешил всем пользователям получать доступ к пути веб-API.

    <location path="api">
        <system.web>
            <authorization>
                <allow users="*" />
            </authorization>
        </system.web>
    </location>
    
  3. Затем я определяю класс фильтра безопасности и реализую мой собственный лог c для аутентификации и авторизации по запросу.

    public class BasicAuthenticationIdentity : GenericIdentity
    {
        public BasicAuthenticationIdentity(string name, string password)
            : base(name, "Basic")
        {
            this.Password = password;
        }
    
        /// 
        /// Basic Auth Password for custom authentication
        /// 
        public string Password { get; set; }
    }
    
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class BasicAuthenticationFilter : AuthorizationFilterAttribute
    {
        bool Active = true;
    
        public BasicAuthenticationFilter()
        { }
    
        ///
        /// Overriden constructor to allow explicit disabling of this
        /// filter's behavior. Pass false to disable (same as no filter
        /// but declarative)
        ///
        ///
        public BasicAuthenticationFilter(bool active)
        {
            Active = active;
        }
    
        ///
        /// Override to Web API filter method to handle Basic Auth check
        ///
        ///
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            if (Active)
            {
                var identity = ParseAuthorizationHeader(actionContext);
                if (identity == null)
                {
                    Challenge(actionContext);
                    return;
                }
    
                if (!OnAuthorizeUser(identity.Name, identity.Password, actionContext))
                {
                    Challenge(actionContext);
                    return;
                }
    
                var principal = new GenericPrincipal(identity, null);
    
                Thread.CurrentPrincipal = principal;
    
                // inside of ASP.NET this is required
                //if (HttpContext.Current != null)
                //    HttpContext.Current.User = principal;
    
                base.OnAuthorization(actionContext);
            }
        }
    
        ///
        /// Base implementation for user authentication - you probably will
        /// want to override this method for application specific logic.
        /// 
        /// The base implementation merely checks for username and password
        /// present and set the Thread principal.
        /// 
        /// Override this method if you want to customize Authentication
        /// and store user data as needed in a Thread Principle or other
        /// Request specific storage.
        ///
    
        protected virtual bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
        {
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                return false;
    
            return true;
        }
    
        ///
        /// Parses the Authorization header and creates user credentials
        ///
        protected virtual BasicAuthenticationIdentity ParseAuthorizationHeader(HttpActionContext actionContext)
        {
            string authHeader = null;
            var auth = actionContext.Request.Headers.Authorization;
            if (auth != null && auth.Scheme == "Basic")
                authHeader = auth.Parameter;
    
            if (string.IsNullOrEmpty(authHeader))
                return null;
    
            authHeader = Encoding.Default.GetString(Convert.FromBase64String(authHeader));
    
            var tokens = authHeader.Split(':');
            if (tokens.Length < 2)
                return null;
    
            return new BasicAuthenticationIdentity(tokens[0], tokens[1]);
        }
    
        ///
        /// Send the Authentication Challenge request
        ///
        void Challenge(HttpActionContext actionContext)
        {
            var host = actionContext.Request.RequestUri.DnsSafeHost;
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            //actionContext.Response = actionContext.Request.CreateUserNoAccessResponse();
            actionContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", host));
        }
    }
    

    public class MyBasicAuthenticationFilter : BasicAuthenticationFilter
    {
        public MyBasicAuthenticationFilter()
        { }
    
        public MyBasicAuthenticationFilter(bool active)
            : base(active)
        { }
    
        protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
        {
            return true;
            //MembershipHelper Members = new MembershipHelper(UmbracoContext.Current);
    
            //if (Members.Login(username, password))
            //{
            //    // Here you can also check against a specific member type or member group
    
            //    Members.Logout();
            //    return true;
            //}
            //return false;
        }
    }
    
    [MyBasicAuthenticationFilter]
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        public List<string> Get()
        {
            return new List<string>() { "Value 1", "Value 2" };
        }
    }
    

    var authHeaders = {};
    authHeaders.Authorization = 'Basic ' + atob(username + ":" + password);
    $.ajax({
       url: "http://localhost:49501/api/values",
       type: "GET",
       headers: authHeaders,
       success: function (response) {
       }
    });
    
...