如何通过WebRequest调用MVC操作并通过Active Directory验证请求?

时间:2012-12-07 22:24:33

标签: c# asp.net-mvc-3 web-services authentication active-directory

我知道标题是满口的。我已经掌握了大部分的东西。如果我能做我正在尝试的事情,我只需要确认。

我正在使用ASP.NET MVC 3.我有一个应用程序,它具有我使用的控制器,就像一个Web服务。控制器上有一个方法,它返回一个字符串,即json。此方法根据活动目录对用户进行身份验证。

对上述应用程序执行WebRequest的应用程序也是MVC应用程序。此应用程序(为了在没有特定用户名和密码的情况下查询AD)正在web.config中使用模拟。该应用程序模拟有权查询AD的帐户;但是,页面上用户的信息(例如他们所在的组)是我验证的。

简而言之(我并不完全理解这一部分),模仿是严格的,因此ASP.NET可以查询Active Directory。当我查询活动目录以获取其信息时,加载页面的用户仍被视为自己。

AD代码如下所示(此代码有效):

   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站点不允许匿名访问。

使用AD信息的服务方法工作正常。问题似乎是通过WebRequest传递凭据来调用此方法并返回JSON。

我调用该操作的WebRequest代码如下:

    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 ......还没有工作......

通过WebRequest调用的MVC 3操作类似于:

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;

        }
}       

那么,如果我通过以下网址直接在浏览器中访问MVC 3 Controller / Action会发生什么:

的http://:90 / MyApp的/ Service.aspx / CheckForProxy /报表/ 555

我可以在页面上看到正确的JSON。但是,如果我从同一服务器上的另一个应用程序对此相同的URL进行WebRequest调用,则Active Directory似乎不能轮询它。这肯定是某种权限问题,但我不确定如何解决它,以便服务看到用户的Active Directory信息。

此处的问题是传递给服务的凭据是调用应用程序模拟的帐户的凭据。我应该更改什么来获取服务mvc应用程序以查看执行WebRequest的用户(应用程序是否进行调用,但是用户加载了应用程序)而不是应用程序模拟的帐户?

我对处理这种沟通的其他想法或方法持开放态度。

解决方案每个jmrnet评论

哇,那个评论很有意思。我不知道正在使用什么样的网络魔术,但我将我的网络请求方法修改为:

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

    }

这准确地传递了主要用户的身份。

1 个答案:

答案 0 :(得分:1)

两个想法:

1)您可以在进行WebRequest调用之前尝试强制模拟。像这样:

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

2)您可以在WebRequest调用中传递用户,在服务端从AD获取用户身份,然后使用上述代码的变体来模拟它们。

以下链接详细介绍了上面使用的模拟代码: http://msdn.microsoft.com/en-us/library/w070t6ka.aspx