如何调用一个MVC动作通过的WebRequest和验证通过Active Directory的要求?动作、MVC、WebRequest、Directory

2023-09-08 12:49:34 作者:沉默〃宣泄不可一世的高傲

我知道这个题目很拗口。我已经得到了大多数事情已经到位。我只需要确认,如果我可以做什么,我试图。

I know the title is a mouthful. I've got most things in place already. I just need confirmation on if I can do what I'm attempting.

我使用ASP.NET MVC 3,我有一个应用程序,它具有控制,我使用类似的Web服务。还有就是控制器上的一个方法,它返回一个字符串,它是JSON。此方法验证对Active Directory的用户。

I'm using ASP.NET MVC 3. I have one application that has controller that I use like a web service. There is a single method on the controller and it returns a string, which is json. This method authenticates the user against active directory.

这执行的WebRequest上述一项的应用也MVC应用程序。此应用程序(以便查询AD没有一个特定的用户名和密码)是使用模拟在web.config中。该应用程序模仿,有查询AD权限的帐户;但是,用户的页面上的信息(如哪些群体,他们是在)是我验证对。

The application that performs a WebRequest to the above one is also an MVC application. This application (in order to query AD without a specific user name and password) is using impersonation in the web.config. The application impersonates an account that has permission to query AD; however, the information of the user on the page (such as what groups they're in) is what I validate against.

在短期(我不完全理解这部分),该模拟是严格意义上ASP.NET可以查询Active Directory。用户加载页面时,我Active Directory中查询自己的信息仍视为自己。

In short (and I don't entirely understand this part), the impersonation is strictly so ASP.NET can query Active Directory. Users loading the page are still seen as themselves when I query active directory for their information.

广告code如下所示(本code工作):

The AD code looks like the following (this code works):

   public static ADUserInfo GetUserInfo(IPrincipal User)
    {
        StringBuilder userAdInfo = new StringBuilder();
        ADUserInfo userInfo = new ADUserInfo();
        String domain = ConfigurationManager.AppSettings["ADdomain"];

        try
        {
            using (var context = new PrincipalContext(ContextType.Domain, domain))
            {
                if (User == null)
                    userAdInfo.AppendLine("User is null.");
                else if (User.Identity == null)
                    userAdInfo.AppendLine(" User is not null. User.Identitiy is.");
                else
                    userAdInfo.AppendLine(" Neither User nor User.Identity is null. " +
                        User.Identity.Name);

                using (var user = UserPrincipal.FindByIdentity(context, User.Identity.Name))
                {
                    userInfo.FullName = user.Name;
                    userInfo.Email = user.EmailAddress;
                    userInfo.AssociateId = user.EmployeeId;
                    userInfo.DomainName = User.Identity.Name;
                    userInfo.SamAccountName = user.SamAccountName;
                    userInfo.DistinguishedUserName = user.DistinguishedName;
               }
            }
        }
        catch (Exception e)
        {
            LogUtil.WriteException(e);
        }
        return userInfo;
    }

此应用程序的IIS站点不允许匿名访问。

The IIS site for this application does not allow anonymous access.

使用AD信息服务方法工作正常。这个问题似乎传递凭据通过WebRequest的调用这个方法,并得到JSON返回。

The service method that uses AD information works fine. The issue seems to be passing credentials through a WebRequest to call this method and get JSON returned.

我的WebRequest code调用的操作是这样的:

My WebRequest code to call the action looks like:

    public class WebRequestUtil
    {
        public static StreamReader GetWebRequestStream(
             string url,
             string contentType,
             bool useDefaultCredentials)
        {
            var request = WebRequest.Create(url);
            request.ContentType = contentType;
            request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
            //request.UseDefaultCredentials = useDefaultCredentials;
            //ICredentials ic = new NetworkCredential();

            //request.Credentials = 
            var response = (HttpWebResponse)request.GetResponse();
            return new StreamReader(response.GetResponseStream());
        }
    }

我玩的ImpersonationLevel ...没有奏效尚未....

I'm playing with the ImpersonationLevel...hasn't worked yet....

通过WebRequest的被调用时的MVC 3动作看起来是这样的:

The MVC 3 action being called via the WebRequest looks something like:

public class ProxyServiceController : Controller
    {

        public ProxyServiceController()
        {

        }

       public string CheckForProxy(string applicationName, string associateId)
        {
            RequestResultDetails requestDetails = new RequestResultDetails();
            string json = string.Empty;

            //This correctly gets the Active directory information for the user
            //and fills out a custom ADUserInfo object.
            **ADUserInfo adUserInfo = ADService.GetUserInfo(this.User);**

            try
            {

                if (!ADService.DoesUrlDataMatchAD(
                                adUserInfo,
                                associateId)
                    )
                {
                    throw new Exception(StaticText.UserDataMismatch);
                }

                resultList = //query db for data given the associateId

                if (resultList.ListIsNotNullOrEmpty())
                {
                    requestDetails.RelationshipExists = true;
                }
                else
                {
                    requestDetails.RelationshipExists = false;
                }

                requestDetails.Details = resultList;

            }
            catch (Exception e)
            {
                LogUtil.WriteException(e);
                requestDetails.ErrorProcessingRequest = true;
                requestDetails.ErrorDetails = ErrorProcessing.GetFullExceptionDetails(e);
            }

            json = JsonConvert.SerializeObject(requestDetails);

            LogUtil.Write("json: " + json);

            return json;

        }
}       

那么,什么情况是,如果我在浏览器中通过类似URL进入MVC 3控制器/动作直接:

So what happens is that, if I go to the MVC 3 Controller/Action directly in the browser via a url like:

HTTP://:90 / MyApp的/ Service.aspx / CheckForProxy /报告/ 555

http://:90/MyApp/Service.aspx/CheckForProxy/Reporting/555

我可以看到页面上的正确的JSON。但是,如果我做一个WebRequest的呼叫从另一个应用程序,在同一服务器上的此相同的URL,Active Directory中似乎并不像它可以查询。这肯定是某种权限问题,但我不知道如何让服务看到用户的Active Directory信息,解决问题。

I can see the correct JSON on the page. However, if I make a WebRequest call to this same URL from another application that is on the same server, Active Directory doesn't seem like it can be polled. This is definitely some kind of permissions issue, but I'm not sure how to resolve it so the service sees the user's Active Directory information.

这里的问题是,所述凭证被传递给服务是那些调用应用程序正在模拟的帐户。怎么修改我得到的服务MVC应用程序,看看执行的WebRequest用户(以及应用程序进行呼叫,但用户加载应用程序),而不是该应用程序正在模拟账户?

The problem here is that the credentials being passed to the service are those of the account the calling application is impersonating. What do I change to get the service mvc application to see the user performing the WebRequest (well the app makes the call, but the user loads the app) and not the account that application is impersonating?

我开到其他的想法或方法来处理这​​种通信。

I'm open to other thoughts or methods for handling this communication.

解决方案PER jmrnet注释

哇,这意见是当场上。我不知道是什么样的魔力网络正在工作,但我修改我的Web请求的方法:

Wow, that comment was spot on. I have no idea what kind of web magic is being worked, but I revised my web request method to:

  public static StreamReader GetWebRequestStream(
         string url,
         string contentType,
         bool useDefaultCredentials,
         IPrincipal user)
    {

        var impersonationContext = ((WindowsIdentity)user.Identity).Impersonate();            
        var request = WebRequest.Create(url);

        try
        {
            request.ContentType = contentType;
            request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;
            request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            var response = (HttpWebResponse)request.GetResponse();
            return new StreamReader(response.GetResponseStream());
        }
        catch (Exception e)
        {
            impersonationContext.Undo();
            throw e;
        }

    }

这准确地传递沿主体用户的身份。

And this accurately passes along the principal user's identity.

推荐答案

两个想法:

1)你可以尝试迫使模拟你让你的WebRequest调用之前。像这样的:

1) You could try forcing impersonation before you make your WebRequest call. Like this:

var impersonationContext = ((WindowsIdentity)User.Identity).Impersonate();
//Make your WebRequest call here...
impersonationContext.Undo();

2),你可以通过用户在通话的WebRequest,在服务端得到AD用户身份,然后使用上述code的变化来冒充他们。

2) You could pass the user in the WebRequest call, in the service side get the user identity from AD, then use a variation of the above code to impersonate them.

下面是更多地谈论上面使用的模拟code链接: http://msdn.microsoft.com/en-us/library/w070t6ka.aspx

Here is a link that talks more about the impersonation code used above: http://msdn.microsoft.com/en-us/library/w070t6ka.aspx