我有一个ASP .NET MVC5应用程序,其中我没有使用Windows身份验证。
一切正常,直到我尝试在开发它的域之外运行该应用程序,并且(无论出于何种原因)得到:
The trust relationship between this workstation and the primary domain failed.
当我试图做User.IsInRole("Admin")
.
我正在使用自定义Identity
、Role
、IdentityStore
、RoleStore
等。NET的Identity
和我可以看到用户和角色数据正在从(MongoDB)数据库中正确检索。
关于这个问题有很多问题,但它们来自想要在其 MVC 应用程序中使用 Windows 身份验证和模拟的人:
使用 Windows 身份验证时,调用 IsInRole 时,主域和受信任域之间的信任关系失败
如何配置 Windows 身份验证/模拟 + IIS 7 + MVC
主域和受信任域之间的信任关系失败
My.User.IsInRole("Role Name") 在 Windows 7 上抛出信任关系错误
那么,如果我不使用Active Directory并且(据我所知)不做任何可能取决于PC域的事情,为什么我会得到这个SystemException
呢?我是否缺少某些配置(在我的Web.config
或 IIS Express 中)?
编辑:
好的,所以缩小一点...
我的User.IsInRole("Admin")
行位于_Layout.cshtml
视图中的if()
语句内(即,根据角色知道要在导航栏中显示的内容)。
我现在知道我只在没有任何用户经过身份验证并且我不在用于开发的域中时才收到上述错误。如果我在该行上放置一个断点,我可以看到User
对象是一个System.Security.Principal.WindowsIdentity
,其基础Identity
是System.Security.Principal.WindowsIdentity
。
另一方面,如果用户经过身份验证,则User
对象和 ts Identity
是 System.Security.Claims.ClaimsPrincipal
和 System.Security.Claims.ClaimsIdentity
.
为什么它完全使用 Windows 标识(未经身份验证时)以及如何禁用它?
因此,根据我的 EDIT,我修改了我的_Layout.cshtml
,以便
@if(User.IsInRole("Admin")) {...}
我有
@if(User.Identity.IsAuthenticated && User.IsInRole("Admin")) {...}
这似乎解决了问题。
我相信问题是ASP .NET Identity
在没有用户进行身份验证时使用空WindowsIdentity
,当我尝试检查User.IsInRole时,它将尝试根据我没有的活动目录检查WindowsIdentity的角色。显然,在尝试检查其角色之前,我应该首先检查用户是否登录,所以我过错了。
但是,即使上面的更改似乎修复了我的代码,我也非常有兴趣了解有关此行为的更多信息:为什么在没有用户进行身份验证时使用空System.Security.Principal.WindowsIdentity
。我会接受任何解释这一点的答案。
我遇到了这个问题 - 如果我测试了一个不存在的活动目录组,它对我来说失败了。
确保您使用的是现有的组!
Windows身份验证 Asp.Net Core 3.1时遇到了这个问题,但是在搜索互联网时首先出现了这个线程。我最终通过用以下内容修饰控制器类声明来解决此问题:
using Microsoft.AspNetCore.Authorization;
[Authorize]
public class SetupController : Controller
希望这对使用 Windows 身份验证并遇到相同错误的人有所帮助。
我们在新的生产服务器上遇到了同样的问题。使用标识框架并使用 web.config 文件限制对特定目录的访问,拒绝任何未经身份验证的用户。当未经身份验证的用户尝试访问此目录中包含任何User.IsInRole("RoleName")
代码的页面时,他们将获得"信任关系..."错误。
其他SO答案中提到的任何修复程序都不适合我们。
事实证明,我们只需要在IIS中启用表单身份验证 - 问题解决了。
"主域和工作站之间的信任关系已失败"错误消息通常要求从域中删除计算机,然后重新加入。现在有几种方法可以做到这一点。如上面的链接中包含的,有关如何在显示错误的计算机上或远程执行此操作的说明。您也可以在Active Directory和PowerShell中执行此操作。
<authorization>
<allow roles="priDomain Users" users="pridomain_user" />
<deny users="?" />
</authorization>
- 确保 web.config 文件中有上述行,并使用正确的用户名填写用户字段。
我刚刚在我们的系统中解决了这个问题,不幸的是,其他建议都不适合我。此问题是由代码尝试访问的网络文件夹中的孤立 SID 引起的。删除后,它又开始工作。
我在自定义身份验证模块中遇到了完全相同的情况,并且在执行IsInRole时遇到了相同的错误。排名最高的解决方案(User.Identity.IsAuthenticated && ...)没有帮助。所以,我玩了很多。最后,我发现我必须从web.config文件中的模块声明中删除(preCondition="managedHandler")属性。因此,而不是:
<system.webServer>
...
<modules>
...
<add name="CompanyAuthentication" type="Company.Authentication.AuthHttpHandler" preCondition="managedHandler" />
</modules>
我必须有:
<system.webServer>
...
<modules>
...
<add name="CompanyAuthentication" type="Company.Authentication.AuthHttpHandler" />
</modules>
这对我来说是诀窍!
对我来说,缺少整个成员资格提供程序配置标记。在我从我们以前的一个应用程序中复制这些后,它工作正常。
<system.web>
<authentication mode="Windows" />
<compilation debug="true" targetFramework="4.7.1" />
<httpRuntime targetFramework="4.7.1" />
<httpModules>
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
<profile defaultProvider="DefaultProfileProvider">
<providers>
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<membership defaultProvider="DefaultMembershipProvider">
<providers>
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager defaultProvider="CustomRoleProvider" enabled="true" cacheRolesInCookie="false">
<providers>
<add name="CustomRoleProvider" type="ABC.ABCModels.ABCRoleProvider" />
</providers>
</roleManager>
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
就我而言,我没有使用User.Identity
而是Thread.CurrentPrincipal.Identity.Name
因此,当我处理这行代码时:
Thread.CurrentPrincipal.IsInRole("admin");
这就是我将遇到相同的错误消息的地方:
The trust relationship between this workstation and the primary domain failed.
遇到相同问题的原因有两种,当然还有我所做的修复:
- 我与我的 VPN 断开连接。这将查找不存在的角色,因为我没有与我的 VPN 连接,也没有与我的 AD 帐户连接。
- 如果我与我的VPN连接,并且根据上面的代码不存在角色
admin
,它肯定会触发相同的错误消息。
值得分享我如何解决我的情况,因为这些答案帮助我弄清楚了。
我们允许/限制通过web.config
访问页面,这是在接触任何代码之前发生的(所以断点在哪里并不重要,错误来了)。
由于这也并不惊人,我决定在代码中手动实现此验证,而不是使用web.config
验证。
我们的web.config
曾经看起来像这样:
<configuration>
<system.web>
<authorization>
<allow roles="10,5"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
我们已更改为:
- 创建了一个继承自主页的页面(称为受限页面)
- 此页面有一个名为
RequiredAccessLevel
的受保护变量 - 页面的 OnLoad 我们检查用户是否具有
RequiredAccessLevel
角色,如果不是,我们将重定向到自定义访问拒绝页面 - 使应该具有此限制的页面继承自
RestrictedPage
而不是Page
- 在继承自
RestrictedPage
的页面的构造函数上,我们设置了必要的访问级别
喜欢这个:
受限页面.cs
public class RestrictedPage : Page
{
protected int[] RequiredAccessLevel { get; set; } = { };
protected override void OnLoad(EventArgs e)
{
if (RequiredAccessLevel.Length > 0)
{
var allowed = false;
foreach (var ral in RequiredAccessLevel)
{
if (Page.User.IsInRole(ral.ToString()))
{
allowed = true;
break;
}
}
if (!allowed)
{
Response.Redirect("~/AccessDenied.aspx");
}
}
base.OnLoad(e);
}
}
示例.cs
public partial class Example: RestrictedPage
{
public Example()
{
RequiredAccessLevel = new[] {10};
}
}