我正在为 ASP.NET MVC 构建自定义权限系统,因为 MVC 附带的授权系统不够灵活,无法满足我们的需求。这包括与 View 、CSS 和 JavaScript 一起打包到 DLL 中的 MVC 区域。我已经进行了单元测试,但现在我正在尝试通过浏览器创建功能测试。这些功能测试将在我的计算机本地或持续集成服务器上运行。
我正在构建的权限系统不进行身份验证。它只是处理授权。理想情况下,我想为每个测试伪造用户登录。我想从任意用户名和密码创建一个用户 session ,而不是使用他们的密码保留一个单独的用户表,并针对它进行身份验证。
我尝试在 AccountController
的 session 中设置 GenericPrincipal
对象,然后在每次请求之前设置 HttpContext.Current.User
,但是该请求始终被视为未经身份验证:
账户 Controller
[Authorize]
public class AccountController : Controller
{
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string ReturnUrl)
{
if (ModelState.IsValid)
{
FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
// Add the fake user to the current session so Global.asax can set
// the user on the current HttpContext to this mock object. (See
// Global.asax, Application_AcquireRequestState)
HttpContext.Session["CurrentUser"] = new GenericPrincipal(new GenericIdentity(model.Username), new string[0]);
if (Url.IsLocalUrl(ReturnUrl))
return Redirect(ReturnUrl);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError(string.Empty, "Username or Password is incorrect");
return View(model);
}
}
Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
// Try to get the mock user from the session, which is set in
// AccountController.Login...
HttpContext.Current.User = HttpContext.Current.Session["CurrentUser"] as IPrincipal;
}
}
}
我创建了一个自定义 Authorize
属性以在我的 MVC Controller 中使用:
public class PermissionLevelAttribute : System.Web.Mvc.AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated || CurrentPrincipal == null)
{
base.OnAuthorization(filterContext);
return;
}
// Custom permissions logic...
}
}
Controller 中此属性的示例用法:
public class BlogPostsController : Controller
{
[PermissionLevel(Roles="Blogs.Posts.Edit.Update")]
public ActionResult Edit(int id)
{
// ...
}
}
当我执行此操作时,filterContext.HttpContext.Request.IsAuthenticated
属性始终为 false,并且它会退出 OnAuthorization
方法。
如何在 ASP.NET MVC 中伪造或模拟用户登录,以便创建 HttpContext.Current.Session
对象并设置 HttpContext.Current.User
?
最佳答案
这个解决方案并没有真正创建一个“模拟”用户,而是创建了一个假用户并且不检查用户名和密码。为此,您需要进行两项主要更改:
重写
AccountController
,使其实际上不检查用户名和密码[Authorize] public class AccountController : Controller { // // GET: /Account/Login [AllowAnonymous] public ActionResult Login(string returnUrl) { ViewBag.ReturnUrl = returnUrl; return View(); } // // POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult Login(LoginViewModel model, string ReturnUrl) { if (ModelState.IsValid) { FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe); if (Url.IsLocalUrl(ReturnUrl)) return Redirect(ReturnUrl); return RedirectToAction("Index", "Home"); } ModelState.AddModelError(string.Empty, "Username or Password is incorrect"); return View(model); } // // GET: /Account/LogOff public ActionResult LogOff() { FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } }
删除或注释掉 Web.config 中与 OWIN 相关的配置设置:
<configuration> <system.webServer> <modules> <!--<remove name="FormsAuthentication" />--> </modules> </system.webServer> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!--<dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly>--> </assemblyBinding> </runtime> </configuration>
这将允许您以任意用户身份使用任意密码登录。
重要提示:显然,我不会为 Web 应用程序的生产版本执行此操作。我正在构建一个 MVC 区域作为 NuGet 包,并将该包安装在一个干净的 MVC 项目上,以针对集成的 NuGet 包和 MVC 应用程序编写自动化测试。这就是我能够使用此解决方案的原因。
关于c# - 如何使用 ASP.NET MVC 伪造或模拟用户登录(身份验证)以进行功能测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35039978/