C# 使用ASP.NET Web API进行并行基本和表单身份验证

C# 使用ASP.NET Web API进行并行基本和表单身份验证,c#,asp.net-mvc,.net-4.0,azure,asp.net-web-api,C#,Asp.net Mvc,.net 4.0,Azure,Asp.net Web Api,免责声明:首先,我要说我是MVC4+WebAPI+Web服务的新手,一般来说+JQuery。我可能从错误的角度攻击它 我正在尝试在C#中为.NET4构建一个Web MVC应用程序+Web API,以便在Azure中部署。移动客户端(iOS,使用RestKit)将使用web api Web MVC应用程序将相对简单。我们希望对它和SimpleMembership使用表单身份验证—我们实现了这一点,并且工作得很好 我们将使用JQuery(Knockout)脚本中的WebAPI方法填充Web页面的各个

免责声明:首先,我要说我是MVC4+WebAPI+Web服务的新手,一般来说+JQuery。我可能从错误的角度攻击它

我正在尝试在C#中为.NET4构建一个Web MVC应用程序+Web API,以便在Azure中部署。移动客户端(iOS,使用RestKit)将使用web api

Web MVC应用程序将相对简单。我们希望对它和SimpleMembership使用表单身份验证—我们实现了这一点,并且工作得很好

我们将使用JQuery(Knockout)脚本中的WebAPI方法填充Web页面的各个部分。因此,我们希望JQuery使用表单身份验证验证的相同身份

然而,其想法是移动客户端可以直接调用Web Api。没有针对这些的表单身份验证

我们一直在关注Thinktecture身份模型()。我们将BasicAuth和AcessKey处理程序添加到配置中,它可以正常工作(请参见下面的代码)

当您尝试在未经身份验证的情况下访问webapi时,浏览器将显示“基本身份验证”对话框并按预期工作

“问题”在于,当您已经通过表单身份验证登录并尝试调用Web Api方法时,仍然会出现“基本身份验证”对话框。换句话说,ThinktectureIdentityModel似乎完全忽略了表单身份验证

我的问题是:

  • 我的期望正确吗?一旦我完成了表单身份验证,我就不应该做任何其他事情来让JQuery脚本等从同一个浏览器用户会话访问Web API
  • 我怎么修理它
  • 如果我的期望不正确;这是怎么回事?ie:如何使JQuery脚本进行身份验证
  • 我知道Stackoverflow中有很多类似的问题,老实说,我查了很多资料,看了很多视频,等等,但要么我遗漏了一些明显的东西,要么没有关于这方面的清晰文档供新技术人员参考

    我感谢你的帮助。谢谢

    public static AuthenticationConfiguration CreateConfiguration()
    {
    var config = new AuthenticationConfiguration
            {
                DefaultAuthenticationScheme = "Basic",
                EnableSessionToken = true,
                SetNoRedirectMarker = true
            };            
    
    config.AddBasicAuthentication((userName, password) => userName == password, retainPassword: false);
    config.AddAccessKey(token =>
            {
                if (ObfuscatingComparer.IsEqual(token, "accesskey123"))
                {
                    return Principal.Create("Custom",
                        new Claim("customerid", "123"),
                        new Claim("email", "foo@customer.com"));
                }
    
                return null;
            }, AuthenticationOptions.ForQueryString("key"));
    

    这是我先前提出的解决这个问题的方法

    注意:此解决方案不涉及Thinktecture身份模型

    我有一个抽象类,它是一个委托处理程序。您可以通过安装最新的stable来获得此处理程序

    如果请求已通过身份验证(例如:通过表单身份验证),则可以向此基本身份验证处理程序发出提示,以禁止身份验证过程。您需要注册的自定义处理程序如下所示:

    public class MyApplicationAuthHandler : BasicAuthenticationHandler {
    
        public MyApplicationAuthHandler() 
            : base(suppressIfAlreadyAuthenticated: true) { }
    
        protected override IPrincipal AuthenticateUser(
            HttpRequestMessage request, 
            string username, 
            string password, 
            CancellationToken cancellationToken) { 
    
            //this method will be called only if the request
            //is not authanticated.
    
            //If you are using forms auth, this won't be called
            //as you will be authed by the forms auth bofore you hit here
            //and Thread.CurrentPrincipal would be populated.
    
            //If you aren't authed:
            //Do you auth here and send back an IPrincipal 
            //instance as I do below.
    
            var membershipService = (IMembershipService)request
                .GetDependencyScope()
                .GetService(typeof(IMembershipService));
    
            var validUserCtx = membershipService
                .ValidateUser(username, password);
    
            return validUserCtx.Principal;
        }
    
        protected override void HandleUnauthenticatedRequest(UnauthenticatedRequestContext context) {
    
            // Do nothing here. The Autharization 
            // will be handled by the AuthorizeAttribute.
        }
    }
    
    最后一步,您需要将
    System.Web.Http.AuthorizeAttribute
    (而不是
    System.Web.Mvc.AuthorizeAttribute
    )应用于控制器和操作方法,以便为特定角色和用户授予授权


    我希望这有助于解决您的问题。

    您好,这很好。然而,“IMembershipService”接口从何而来?(它似乎不是WebAPIDoongle或标准.net4MVC的一部分)。注意,您的类可以工作,我希望同一个类也能处理API键,但是,我相信我可以添加该功能。我现在的主要问题是如何使用“WebSecurity”类根据数据库验证用户,并返回主体(我可以执行WebSecurity.Login,但这很简单)。顺便说一句:当从浏览器(Chrome)进行测试时,如果用户未登录,它不会强制浏览器提供基本身份验证。虽然这对我的移动客户端不是必需的,但它便于测试。我也会检查一下。@rufo-IMembershipService是我自己的实现。我把它放在那里是为了让你有个想法。你可以用你自己的impl来代替它。@rufo这里是答案。由于源代码对它们都可用,您可以混合使用它们并创建自己的。@rufo如果您想要这种行为,请保持方法不变。正如您在我的示例中所看到的,我将其替换为我自己的行为,它根本不做任何事情,并将授权留给AuthorizeAttribute。