我正在尝试为我正在开发的 Intranet 站点实现以下场景:
- 当用户在与网站同域的PC上登录并连接到与网站相同的网络时,访问内网站点时,他将自动登录(windows认证)
- 当同一用户使用同一台PC登录与网站相同的域但在其他网络(例如家庭网络)作为网站时,他将自动登录(Windows身份验证)
- 当同一用户从他/她的不属于域和网络的家用 PC 打开网站时,他将被重定向到表单身份验证登录页面,并且能够使用他/她的 AD 凭据登录(表单身份验证具有 AD 会员资格)
- 当没有 AD 帐户且不在属于域的 PC 上的其他用户时,他将被重定向到表单身份验证登录页面并能够使用他/她的 SQL 用户凭据登录(带有 SQL 成员身份的表单身份验证)
除了 1 个重要步骤外,我几乎可以完成这项工作。我现在的代码是这样的:
全球.asax
protected void Application_EndRequest(object sender, EventArgs e)
{
// we only want 302 redirects if they are for login purposes
if (this.Response.StatusCode == 302 && this.Response.RedirectLocation.Contains("/WinLogin"))
{
if (Request.UserHostAddress.StartsWith("10.1.34") || Request.UserHostAddress.StartsWith("10.1.35"))
{
this.Response.StatusCode = 401;
// note that the following line is .NET 4.5 or later only
// otherwise you have to suppress the return URL etc manually!
this.Response.SuppressFormsAuthenticationRedirect = true;
}
}
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated && HttpContext.Current.User.Identity is WindowsIdentity)
{
// note that we will be stripping the domain from the username as forms authentication doesn't capture this anyway
// create a temp cookie for this request only (not set in response)
var tempCookie = FormsAuthentication.GetAuthCookie(Regex.Replace(HttpContext.Current.User.Identity.Name, ".*\\\\(.*)", "$1", RegexOptions.None), false);
// set the user based on this temporary cookie - just for this request
// we grab the roles from the identity we are replacing so that none are lost
HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(FormsAuthentication.Decrypt(tempCookie.Value)), (HttpContext.Current.User.Identity as WindowsIdentity).Groups.Select(group => group.Value).ToArray());
// now set the forms cookie
FormsAuthentication.SetAuthCookie(HttpContext.Current.User.Identity.Name, false);
}
}
WinLogin.aspx:
var membershipProvider1 = Membership.Providers["MyAdMembershipProvider"];
var membershipProvider2 = Membership.Providers["MySqlMembershipProvider"];
if (membershipProvider1.ValidateUser(TextBox1.Text, TextBox2.Text) || membershipProvider2.ValidateUser(TextBox1.Text, TextBox2.Text))
{
// set the forms auth cookie
FormsAuthentication.SetAuthCookie(TextBox1.Text, false);
// reset request.isauthenticated
var authCookie = System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');
System.Web.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, false);
}
网页配置
<authentication mode="Forms">
<forms name=".ASPXFORMSDEMO" loginUrl="WinLogin.aspx" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<location path="/WinLogin.Aspx">
<system.web>
<authorization>
<allow users="?"/>
</authorization>
</system.web>
</location>
IIS 中的设置
网站根级别
- 启用匿名身份验证
- 表单身份验证已启用
- Windows 身份验证已启用
WebLogin.aspx 级别
- 启用匿名身份验证
- 表单身份验证已启用
- Windows 身份验证已禁用
除了我定义是否可以使用 Windows 身份验证的部分之外,我的所有场景都有效。使用我现在的设置,只有本地网络中的 PC 将继续使用 Windows 身份验证。每当我在网络外使用我的电脑时,我都会看到表单身份验证登录屏幕。
有没有人建议我如何确定是否应该使用 Windows 身份验证。我一直在使用当前用户登录的用户名并检查它的域并使用它,但我似乎无法从网站的 IIS 设置中获得它。
提前致谢!