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

ruf*_*ufo 13 c# asp.net-mvc .net-4.0 azure asp.net-web-api

免责声明:首先我要说的是我对MVC4 + Web Api + Web服务+ JQuery的新手.我可能会以错误的角度攻击这个.

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

Web MVC应用程序将相对简单.我们想使用Forms Authentication和SimpleMembership - 我们已经实现并且工作正常.

我们将使用JQuery(Knockout)脚本中的Web API方法来填充网页的各个部分.因此,我们希望JQuery使用由Forms Authentication验证的相同身份.

但是,我们的想法是Web Api可以由移动客户端直接调用.没有表格认证.

我们一直在研究Thinktecture身份模型(http://nuget.org/packages/Thinktecture.IdentityModel https://github.com/thinktecture/Thinktecture.IdentityModel.40).我们将BasicAuth和AcessKey处理程序添加到配置中并且它可以工作(请参阅下面的代码).

当您尝试访问webapi而未经过身份验证时,浏览器将显示基本身份验证对话框并按预期工作.

"问题"是,当您已经通过表单身份验证登录并尝试调用Web Api方法时,您仍然可以获得"基本身份验证"对话框.换句话说,Thinktecture IdentityModel似乎完全忽略了Forms身份验证.

我的问题是:

  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"));
Run Code Online (Sandbox Code Playgroud)

tug*_*erk 6

以下是我之前提出的这个问题的解决方案.

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

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

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

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一步,您需要System.Web.Http.AuthorizeAttribute(不System.Web.Mvc.AuthorizeAttribute)应用于控制器和操作方法,以便为特定角色和用户授予权限.

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