NancyFx和Windows身份验证(NancyFx and Windows Authentica

2019-07-03 21:20发布

我想用NancyFx用于内部网的网络应用程序。 所有的文档和论坛只提表单和基本身份验证。 任何人都成功地使用南希使用Windows身份验证?

还有一些所谓的Nancy.Authentication.Stateless,但我看不出是什么一样(貌似这是用于蜜蜂)。

Answer 1:

我在一个内部项目最近使用过这一点 - 我真的不喜欢它,它关系到你的ASP.NET虚拟主机,但它做的工作:

namespace Blah.App.Security
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Principal;
    using System.Web;

    using Nancy;

    public static class SecurityExtensions
    {
        public static string CurrentUser
        {
            get
            {
                return GetIdentity().Identity.Name;
            }
        }

        public static bool HasRoles(params string[] roles)
        {
            if (HttpContext.Current != null && HttpContext.Current.Request.IsLocal)
            {
                return true;
            }

            var identity = GetIdentity();

            return !roles.Any(role => !identity.IsInRole(role));
        }

        public static void RequiresWindowsAuthentication(this NancyModule module)
        {
            if (HttpContext.Current != null && HttpContext.Current.Request.IsLocal)
            {
                return;
            }

            module.Before.AddItemToEndOfPipeline(
                new PipelineItem<Func<NancyContext, Response>>(
                    "RequiresWindowsAuthentication",
                    ctx =>
                        {
                            var identity = GetIdentity();

                            if (identity == null || !identity.Identity.IsAuthenticated)
                            {
                                return HttpStatusCode.Forbidden;
                            }

                            return null;
                        }));
        }

        public static void RequiresWindowsRoles(this NancyModule module, params string[] roles)
        {
            if (HttpContext.Current != null && HttpContext.Current.Request.IsLocal)
            {
                return;
            }

            module.RequiresWindowsAuthentication();

            module.Before.AddItemToEndOfPipeline(new PipelineItem<Func<NancyContext, Response>>("RequiresWindowsRoles", GetCheckRolesFunction(roles)));
        }

        private static Func<NancyContext, Response> GetCheckRolesFunction(IEnumerable<string> roles)
        {
            return ctx =>
                {
                    var identity = GetIdentity();

                    if (roles.Any(role => !identity.IsInRole(role)))
                    {
                        return HttpStatusCode.Forbidden;
                    }

                    return null;
                };
        }

        private static IPrincipal GetIdentity()
        {
            if (System.Web.HttpContext.Current != null)
            {
                return System.Web.HttpContext.Current.User;
            }

            return new WindowsPrincipal(WindowsIdentity.GetCurrent());
        }

        public static Func<NancyContext, Response> RequireGroupForEdit(string group)
        {
            return ctx =>
                {
                    if (ctx.Request.Method == "GET")
                    {
                        return null;
                    }

                    return HasRoles(group) ? null : (Response)HttpStatusCode.Forbidden;
                };
        }
    }
}

它绕过所有安全检查,如果它的到来,从本地(用于测试),这可能是一个坏主意,但它是一个在防火墙后面的东西,所以它不是这个问题。

不建议你使用它逐字,但可能你指出正确的方向:)



Answer 2:

我需要Windows身份验证与南希一个基本的Intranet应用程序。 我用@Steven罗宾斯答案为出发点,但剥离的事情,我们并不需要再加入其余的人口NancyContext.CurrentUser财产。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using Nancy;
using Nancy.Security;

namespace YourNamespace
{
    /// <summary>
    /// Extensions for Nancy that implement Windows Authentication.
    /// </summary>
    public static class WindowsAuthenticationExtensions
    {
        private class WindowsUserIdentity : IUserIdentity
        {
            private string _userName;

            public WindowsUserIdentity(string userName)
            {
                _userName = userName;
            }

            #region IUserIdentity

            IEnumerable<string> IUserIdentity.Claims
            {
                get { throw new NotImplementedException(); }
            }

            string IUserIdentity.UserName
            {
                get { return _userName; }
            }

            #endregion
        }

        #region Methods

        /// <summary>
        /// Forces the NancyModule to require a user to be Windows authenticated. Non-authenticated
        /// users will be sent HTTP 401 Unauthorized.
        /// </summary>
        /// <param name="module"></param>
        public static void RequiresWindowsAuthentication(this NancyModule module)
        {
            if (HttpContext.Current == null) 
                throw new InvalidOperationException("An HttpContext is required. Ensure that this application is running under IIS.");

            module.Before.AddItemToEndOfPipeline(
                new PipelineItem<Func<NancyContext, Response>>(
                    "RequiresWindowsAuthentication",
                    context =>
                    {
                        var principal = GetPrincipal();

                        if (principal == null || !principal.Identity.IsAuthenticated)
                        {
                            return HttpStatusCode.Unauthorized;
                        }

                        context.CurrentUser = new WindowsUserIdentity(principal.Identity.Name);

                        return null;
                    }));
        }

        private static IPrincipal GetPrincipal()
        {
            if (HttpContext.Current != null)
            {
                return HttpContext.Current.User;
            }

            return new WindowsPrincipal(WindowsIdentity.GetCurrent());
        }

        #endregion

    }
}

您可以使用这样的:

public class YourModule : NancyModule
{
    public YourModule()
    {
        this.RequiresWindowsAuthentication();

        Get["/"] = parameters =>
            {
                //...
            };
    }

}



Answer 3:

使用南希WindowsAuthentication被讨论这个线程 。 达米安·希基提供了一个使用南希,由OWin与WindowsAuthentication托管的例子 。

我稍微修改了代码(除去现在已经过时NancyOwinHost ):

namespace ConsoleApplication1
{
    using System;
    using System.Net;
    using System.Security.Principal;
    using Microsoft.Owin.Hosting;
    using Nancy;
    using Nancy.Owin;
    using Owin;

    internal static class Program
    {
        private static void Main(string[] args)
        {
            using (WebApp.Start<Startup>("http://localhost:9000"))
            {
                Console.WriteLine("Press any key to quit.");
                Console.ReadKey();
            }
        }
    }

    internal sealed class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var listener = (HttpListener) app.Properties["System.Net.HttpListener"];
            listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;

            app.UseNancy();
        }
    }

    public sealed class MyModule : NancyModule
    {
        public MyModule()
        {
            Get[""] = _ =>
            {
                var env = this.Context.GetOwinEnvironment();
                var user = (IPrincipal) env["server.User"];

                return "Hello " + user.Identity.Name;
            };
        }
    }
}

我要特别感谢达米安!


该示例需要以下的NuGet包:

  • Microsoft.Owin.Host.HttpListener
  • Microsoft.Owin.Hosting
  • Microsoft.Owin
  • Nancy
  • Nancy.Owin
  • Owin


Answer 4:

你可以试着帮我完成Nancy.Authentication.Ntlm 。 这绝对是预阿尔法。 我不知道如何实现主要是基于我有限的南希内部的知识几个事情。

目前,该代码挑战客户端,验证答案。 但是,我没通知客户有关此操作的成功。

但我还是努力工作。 真的很难。

我将不胜感激您的意见和拉如有请求。



Answer 5:

站在巨人的sholders,我已经实现了它以这种方式允许认证进行模拟来测试

using System;
using System.Collections.Generic;
using Nancy;
using Nancy.Security;

namespace Your.Namespace
{
    /// <summary>
    /// Extensions for Nancy that implement Windows Authentication.
    /// </summary>
    public static class WindowsAuthenticationExtensions
    {
        private class WindowsUserIdentity : IUserIdentity
        {
            private readonly string _userName;

            public WindowsUserIdentity(string userName)
            {
                _userName = userName;
            }

            #region IUserIdentity

            IEnumerable<string> IUserIdentity.Claims
            {
                get { throw new NotImplementedException(); }
            }

            string IUserIdentity.UserName
            {
                get { return _userName; }
            }

            #endregion
        }

        #region Methods

        /// <summary>
        /// Forces the NancyModule to require a user to be Windows authenticated. Non-authenticated
        /// users will be sent HTTP 401 Unauthorized.
        /// </summary>
        /// <param name="module"></param>
        /// <param name="authenticationProvider"></param>
        public static void RequiresWindowsAuthentication(this NancyModule module, IWindowsAuthenticationProvider authenticationProvider)
        {
            if (!authenticationProvider.CanAuthenticate)
                throw new InvalidOperationException("An HttpContext is required. Ensure that this application is running under IIS.");

            module.Before.AddItemToEndOfPipeline(
                new PipelineItem<Func<NancyContext, Response>>(
                    "RequiresWindowsAuthentication",
                    context =>
                    {
                        var principal = authenticationProvider.GetPrincipal();

                        if (principal == null || !principal.Identity.IsAuthenticated)
                        {
                            return HttpStatusCode.Unauthorized;
                        }

                        context.CurrentUser = new WindowsUserIdentity(principal.Identity.Name);

                        return null;
                    }));
        }

        #endregion

    }
}

IWindowsAuthenticationProvider:

using System.Security.Principal;

namespace Your.Namespace
{
    public interface IWindowsAuthenticationProvider
    {
        bool CanAuthenticate { get; }
        IPrincipal GetPrincipal();
    }
}

WindowsAuthenticationProvider:

using System.Security.Principal;
using System.Web;

namespace Your.Namespace
{
    public class WindowsAuthenticationProvider : IWindowsAuthenticationProvider
    {
        public bool CanAuthenticate
        {
            get { return HttpContext.Current != null; }
        }

        public IPrincipal GetPrincipal()
        {
            if (HttpContext.Current != null)
            {
                return HttpContext.Current.User;
            }

            return new WindowsPrincipal(WindowsIdentity.GetCurrent());
        }
    }
}

实现它是一个有点乱,因为你需要的IWindowsAuthenticationProvided注入到每一个模块

public DefaultModule(IWindowsAuthenticationProvider authenticationProvider) 
        {
            this.RequiresWindowsAuthentication(authenticationProvider);
            Get["/"] = _ => "Hello World";
        }


文章来源: NancyFx and Windows Authentication