NancyFx和Windows身份验证

PPC*_*der 19 .net asp.net windows-authentication nancy

我想将NancyFx用于Intranet Web应用程序.所有文档和论坛仅提及表单和基本身份验证.任何人成功使用Nancy与Windows身份验证?

还有一种名为Nancy.Authentication.Stateless的东西,但我看不出它的作用(看起来像是在Apis中使用).

Gid*_*sey 17

我需要与Nancy进行Windows身份验证以获得基本的Intranet应用程序.我使用@Steven Robbins的答案作为起点,但剥夺了我们不需要的东西,然后添加了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

    }
}
Run Code Online (Sandbox Code Playgroud)

你这样使用它:

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

        Get["/"] = parameters =>
            {
                //...
            };
    }
Run Code Online (Sandbox Code Playgroud)

}


Cod*_*Fox 17

此线程讨论了使用Nancy和WindowsAuthentication.Damian Hickey提供了一个使用Nancy例子,由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;
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

特别感谢达米安!


该示例需要以下NuGet包:

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


Ste*_*ins 8

我最近在一个内部项目中使用过这个 - 我真的不喜欢它,它将你绑定到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;
                };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它绕过所有安全检查,如果它来自本地(用于测试),这可能是一个坏主意,但它是防火墙之后的事情所以它不是一个问题.

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