我知道标题是拗口的。我已经把大部分东西都准备好了。我只需要确认我是否可以做我正在尝试的事情。
我正在使用 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/Reporting/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;
}
}
这准确地传递了主要用户的身份。