仅在MSTest单元测试.Net 4.5中为用PrincipalPermissionAttribute修饰的方法引发Se
本文关键字:方法 Se PrincipalPermissionAttribute Net 单元测试 MSTest 仅在 | 更新日期: 2023-09-27 18:20:49
在将我们的网站从使用旧的Microsoft.IdentityModel类升级到System.IdentityModel类(例如.Net 4.5框架)后,如果我们的MSTest单元测试调用了使用PrincipalPermissionAttribute的方法,则大多数单元测试都开始失败。
例如:
[RequireAuthentication]
[PrincipalPermission(SecurityAction.Demand, Role = "AllowActAs")]
public ActionResult ActAs(int id)
在我们的单元测试中,在调用控制器方法之前,我们之前设置了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;
我试图通过将对象移动到新的类来重新创建这种方法:
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;
然而,每当我调用target.ActAs(id)
时,我都会得到一个SecurityException。我应该注意的是,除非我的用户不在指定的角色中,否则我在实际使用网站时不会收到这个异常,所以这在某种程度上是MSTest环境特有的。
此外,如果我在调用控制器方法之前在单元测试中设置了一个断点,并在手表中检查Thread.CurrentPrincipal.IsInRole("AllowActAs")
,则结果为true
。
此外,如果我在当前线程上使用GenericPrincipal,它将被授予访问该方法的权限,因此它必须与ClaimsPrincipal:有关
GenericPrincipal new_principal = new GenericPrincipal(
new GenericIdentity("Jamie"),
new string[] { "AllowActAs" }
);
Thread.CurrentPrincipal = new_principal;
有人知道这种脱节可能在哪里吗?
返回的完整异常为:
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
我终于明白了。我误解了错误信息。尽管它引用了角色,但实际问题是System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated
是false
。根据ClaimsIdentity上的MSDN页面。IsAuthenticated(http://msdn.microsoft.com/en-us/library/system.security.claims.claimsidentity.isauthenticated(v=vs.110).aspx),如果ClaimsIdentity.AuthenticationType设置为非空字符串,则IsAuthenticated返回true。
由于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;