【问题标题】:Side by side Basic and Forms Authentication with ASP.NET Web API使用 ASP.NET Web API 并排基本和表单身份验证
【发布时间】:2012-10-11 19:54:32
【问题描述】:

免责声明:首先让我说我是 MVC4 + Web Api + 一般 Web 服务 + JQuery 的新手。我可能从错误的角度攻击这个。

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

Web MVC App 会比较简单。我们想对其使用 Forms Authentication 和 SimpleMembership - 我们已经实现并且工作正常。

我们将使用来自 JQuery (Knockout) 脚本的 Web API 方法来填充网页片段。因此,我们希望 JQuery 使用通过 Forms Authentication 认证的相同身份。

但是,这个想法是移动客户端可以直接调用 Web Api。这些没有表单身份验证。

我们一直在研究 Thinktecture 身份模型 (http://nuget.org/packages/Thinktecture.IdentityModelhttps://github.com/thinktecture/Thinktecture.IdentityModel.40)。我们在配置中添加了 BasicAuth 和 AcessKey 处理程序,它可以工作(见下面的代码)。

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

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

我的问题是:

  1. 我的预期正确吗?一旦我完成了表单身份验证,我就不应该做任何其他事情来让 JQuery 脚本等从同一个浏览器用户会话访问 Web API。
  2. 如何解决?
  3. 如果我的预期不正确;这应该如何工作?即:如何使 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"));

【问题讨论】:

    标签: c# asp.net-mvc .net-4.0 azure asp.net-web-api


    【解决方案1】:

    这是我之前提出的这个问题的解决方案。

    注意:此解决方案不涉及 Thinktecture Identity Model。

    我有一个抽象的BasicAuthenticationHandler 类,它是一个委托处理程序。您可以通过安装最新的稳定版WebAPIDoodle NuGet package 来获取此处理程序。

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

    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 或标准 .NET4 MVC 的一部分)。请注意,您的课程有效,我希望同一个课程也处理 API 密钥,但是,我相信我可以添加该功能。我现在的主要问题是如何使用“WebSecurity”类来验证用户对数据库并返回委托人(我可以做 WebSecurity.Login,但这很俗气)。
    • 顺便说一句:从浏览器 (Chrome) 进行测试时,如果用户未登录,它不会强制浏览器提供基本身份验证。虽然这对我的移动客户端来说不是必需的,但它便于测试。我也去看看。
    • @rufo IMembershipService 是我自己的实现。我把它放在那里让你有个主意。你可以用你自己的 impl 替换它。
    • @rufo 这里是ApiKeyAuthenticationHandler。由于它们都可以使用源代码,因此您可以将它们混合并创建自己的源代码。
    • @rufo 如果您想要这种行为,请保持 HandleUnauthenticatedRequest 方法不变。正如您在我的示例中看到的那样,我用自己的行为替换了它,它什么都不做,并将授权留给 AuthorizeAttribute。
    猜你喜欢
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2015-10-11
    • 2014-01-26
    • 2014-03-19
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多