简体   繁体   English

仅在MSTest单元测试.Net 4.5中为使用PrincipalPermissionAttribute装饰的方法引发的SecurityException

[英]SecurityException raised for method decorated with PrincipalPermissionAttribute only in MSTest unit test .Net 4.5

After upgrading our web site from using the older Microsoft.IdentityModel classes to the System.IdentityModel classes (eg .Net 4.5 framework), most of our MSTest unit tests started failing if they called methods that used the PrincipalPermissionAttribute. 将我们的网站从使用较旧的Microsoft.IdentityModel类升级到System.IdentityModel类(例如.Net 4.5框架)后,如果大多数MSTest单元测试调用使用PrincipalPermissionAttribute的方法,则它们开始失败。

For example: 例如:

[RequireAuthentication]
[PrincipalPermission(SecurityAction.Demand, Role = "AllowActAs")]
public ActionResult ActAs(int id)

Within our unit tests, we were previously setting the Thread.CurrentPrincipal before we calling the controller method like so: 在我们的单元测试中,我们之前设置了Thread.CurrentPrincipal,然后再调用控制器方法,如下所示:

List<Microsoft.IdentityModel.Claims.Claim> claims = new List<Microsoft.IdentityModel.Claims.Claim>();
claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "Jamie"));
claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "1234567890"));
claims.Add(new Microsoft.IdentityModel.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "AllowActAs"));

Microsoft.IdentityModel.Claims.ClaimsIdentityCollection claimsCollection = new Microsoft.IdentityModel.Claims.ClaimsIdentityCollection();
claimsCollection.Add(new Microsoft.IdentityModel.Claims.ClaimsIdentity(claims));

Microsoft.IdentityModel.Claims.ClaimsPrincipal new_principal = new Microsoft.IdentityModel.Claims.ClaimsPrincipal(claimsCollection);
Thread.CurrentPrincipal = new_principal;

I have tried to recreate that approach by moving the objects over to the new classes: 我试图通过将对象移至新类来重新创建该方法:

List<System.Security.Claims.Claim> claims = new List<System.Security.Claims.Claim>();
claims.Add(new System.Security.Claims.Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "Jamie"));
claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "1234567890"));
claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "AllowActAs"));

List<System.Security.Claims.ClaimsIdentity> claimsCollection = new List<System.Security.Claims.ClaimsIdentity>();
claimsCollection.Add(new System.Security.Claims.ClaimsIdentity(claims));

System.Security.Claims.ClaimsPrincipal new_principal = new System.Security.Claims.ClaimsPrincipal(claimsCollection);
Thread.CurrentPrincipal = new_principal;

However, whenever I call target.ActAs(id) , I get a SecurityException. 但是,每当我调用target.ActAs(id) ,都会收到SecurityException。 I should note that I am not getting this exception when actually using the web site unless my user is not in the specified role, so this is somehow specific to the MSTest environment. 我应该注意,除非我的用户没有担任指定角色,否则在实际使用网站时不会出现此异常,因此,这在某种程度上特定于MSTest环境。

Additionally, if I set a break-point in the unit test just before calling the controller method and check Thread.CurrentPrincipal.IsInRole("AllowActAs") in the watch, the result is true . 另外,如果在调用控制器方法之前在单元测试中设置了一个断点,并在手表中检查Thread.CurrentPrincipal.IsInRole("AllowActAs") ,则结果为true

Furthermore, if I use a GenericPrincipal on the current thread, it am granted access to the method, so it has to have something to do with the ClaimsPrincipal: 此外,如果我在当前线程上使用GenericPrincipal,则它被授予对方法的访问权限,因此它与ClaimsPrincipal有关:

GenericPrincipal new_principal = new GenericPrincipal(
    new GenericIdentity("Jamie"),
    new string[] { "AllowActAs" }
);

Thread.CurrentPrincipal = new_principal;

Does anyone have any ideas about where the disconnect might be? 是否有人对断开连接的位置有任何想法?

The full exception returned is: 返回的完整异常为:

System.Security.SecurityException: Request for principal permission failed.
   at System.Security.Permissions.PrincipalPermission.ThrowSecurityException()
   at System.Security.Permissions.PrincipalPermission.Demand()
   at System.Security.PermissionSet.DemandNonCAS()
   at Stepp.ProclaimCrm.PortalUI.Controllers.ImpersonateController.ActAs(Int32 id) in c:\ProclaimCRM\ProclaimCRM Portal\Portal-9373-Portal-Based-Accounts\Portal Web Front-End\Controllers\ImpersonateController.cs:line 79
   at Portal_Web_Front_End_Test.ImpersonateTests.ActAsTestPersonWhoHasPreventActAs() in c:\ProclaimCRM\ProclaimCRM Portal\Portal-9373-Portal-Based-Accounts\Portal Web Front-End Test\Controllers\ImpersonateTests.cs:line 465
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.PrincipalPermission
The first permission that failed was:
<IPermission class="System.Security.Permissions.PrincipalPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1">
<Identity Authenticated="true"
Role="AllowActAs"/>
</IPermission>

The demand was for:
<IPermission class="System.Security.Permissions.PrincipalPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1">
<Identity Authenticated="true"
Role="AllowActAs"/>
</IPermission>

The assembly or AppDomain that failed was:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

I finally figured this out. 我终于想通了。 I misunderstood the error message. 我误解了错误信息。 Although it referenced the Role, the actual problems was that System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated was false . 尽管它引用了Role,但实际的问题是System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticatedfalse According to the MSDN page on ClaimsIdentity.IsAuthenticated ( http://msdn.microsoft.com/en-us/library/system.security.claims.claimsidentity.isauthenticated(v=vs.110).aspx ), IsAuthenticated returns true if ClaimsIdentity.AuthenticationType is set to a non-empty string. 根据ClaimsIdentity.IsAuthenticated的MSDN页面( http://msdn.microsoft.com/zh-cn/library/system.security.claims.claimsidentity.isauthenticated(v=vs.110).aspx ),如果以下情况下IsAuthenticated返回true, ClaimsIdentity.AuthenticationType设置为非空字符串。

Since there's a constructor for ClaimsPrincipal that allows you to specify the authentication type, adding the "Test" authentication type fixed my problem: 由于存在ClaimsPrincipal的构造函数,该构造函数允许您指定身份验证类型,因此添加“ Test”身份验证类型可以解决我的问题:

List<System.Security.Claims.Claim> claims = new List<System.Security.Claims.Claim>();
claims.Add(new System.Security.Claims.Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "Jamie"));
claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "1234567890"));
claims.Add(new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "AllowActAs"));

List<System.Security.Claims.ClaimsIdentity> claimsCollection = new List<System.Security.Claims.ClaimsIdentity>();
claimsCollection.Add(new System.Security.Claims.ClaimsIdentity(claims, "Test")); // specify authentication type here!!

System.Security.Claims.ClaimsPrincipal new_principal = new System.Security.Claims.ClaimsPrincipal(claimsCollection);
Thread.CurrentPrincipal = new_principal;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM