且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

并排Basic和窗体身份验证使用的ASP.NET Web API

更新时间:2023-02-17 11:09:45

下面是对于这个问题,我想出了前面的解决方案。

  

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

我有一个抽象的这是一个委托处理程序BasicAuthenticationHandler 类。您可以通过安装最新的稳定 WebAPIDoodle的NuGet包得到这个处理程序。

您可以给一个提示,这个基地基本身份验证处理程序晚饭preSS认证过程中,如果该请求已被验证(例如:通过窗体身份验证)。你需要注册你的自定义处理程序看起来像如下:

 公共类MyApplicationAuthHandler:BasicAuthenticationHandler {

    公共MyApplicationAuthHandler()
        :基地(SUP pressIfAlreadyAuthenticated:真){}

    保护覆盖的IPrincipal authenticateUser的(
        HTT prequestMessage的要求,
        字符串的用户名,
        串密码,
        的CancellationToken的CancellationToken){

        //此方法只被调用,如果请求
        //不authanticated。

        //如果使用窗体身份验证,这将不会被调用
        //你会被窗体身份验证来authed bofore你打这里
        //和Thread.CurrentPrincipal中会被填充。

        //如果你不authed:
        //你权威性这里并发送回一个IPrincipal
        //比如像我这样如下。

        VAR membershipService =(IMembershipService)要求
            .GetDependencyScope()
            .GetService(typeof运算(IMembershipService));

        VAR validUserCtx = membershipService
            .ValidateUser(用户名,密码);

        返回validUserCtx.Principal;
    }

    保护覆盖无效HandleUnauthenticatedRequest(UnauthenticatedRequestContext上下文){

        //这里什么都不做。该Autharization
        //将由AuthorizeAttribute处理。
    }
}
 

作为最后一步,你将需要申请 System.Web.Http.AuthorizeAttribute (而不是 System.Web.Mvc.AuthorizeAttribute )到你的控制器和动作方法给予授权的具体角色和用户。

我希望这可以帮助您解决问题。

Disclaimer: let me start by saying that I am new to MVC4 + Web Api + Web Services in general + JQuery. I might be attacking this on the wrong angle.

I am trying to build a Web MVC App + Web API in C# for .NET 4 to deploy in Azure. The web api will be used by mobile clients (iOS, using RestKit).

The Web MVC App will be relatively simple. We would like to use Forms Authentication for it and SimpleMembership - which we achieved and works fine.

We'll use the Web API methods from JQuery (Knockout) scripts to fill pieces of the web pages. Therefore, we expect the JQuery to use the same identity authenticated by Forms Authentication.

However, the idea is that the Web Api can be called directly by mobile clients. No Forms Authentications for those.

We have been looking at the Thinktecture Identity Model (http://nuget.org/packages/Thinktecture.IdentityModel https://github.com/thinktecture/Thinktecture.IdentityModel.40). We added the BasicAuth and AcessKey handlers to the config and it works (see code below).

When you try to access the webapi without being authenticated the browser displays the basic authentication dialog and works as expected.

The "issue" is that when you ARE already logged in via Forms Authentication and try to call a Web Api method you still get the Basic Authentication dialog. In other words, Thinktecture IdentityModel seems to ignore the Forms Authentication altogether.

My questions are:

  1. Are my expectations correct? that once I have done the forms authentication I shouldn't do anything else to let the JQuery scripts, etc., access the Web API from the same browser user session.
  2. How do I fix it?
  3. If my expectations are not correct; how is this supposed to work? ie: how do I make the JQuery scripts authenticate?

I know there are tons of similar questions in ***, I honestly looked a lot of up, saw videos, etc., but either I am missing something obvious or there is no clear documentation about this for somebody new in the technologies.

I appreciate the help. Thanks.

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"));

Here is the solution for this problem which I have come up with earlier.

Note: This solution doesn't involve Thinktecture Identity Model.

I have an abstract BasicAuthenticationHandler class which is a delegating handler. You can get this handler by installing the latest stable WebAPIDoodle NuGet package.

You can give a hint to this base basic authentication handler to suppress the authentication process if the request has been already authentication (e.g: by forms auth). Your custom handler that you need to register would look like as below:

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.
    }
}

As a final step, you will need to apply System.Web.Http.AuthorizeAttribute (not System.Web.Mvc.AuthorizeAttribute) to your controllers and action methods to give authorization for the specific roles and users.

I hope this helps to solve your problem.