ASP.NET MVC身份验证登录无需密码

34

我被分配修改一个ASP.NET MVC应用程序,使得访问myurl?username=xxxxxx的用户可以自动登录,而无需输入密码。

我已经非常清楚地表明了这是一个很糟糕的想法,因为涉及到许多安全相关的原因和情况,但是负责人还是坚持要这么做。该站点不会对公众开放。

所以:是否有任何方法可以在不使用密码的情况下进行登录,例如通过扩展Microsoft.AspNet.Identity.UserManager并修改AccountController

一些代码:

var user = await _userManager.FindAsync(model.UserName, model.Password);
if (user != null && IsAllowedToLoginIntoTheCurrentSite(user))
{
    user = _genericRepository.LoadById<User>(user.Id);
    if (user.Active)
    {
        await SignInAsync(user, model.RememberMe);

_userManager保存了一个Microsoft.AspNet.Identity.UserManager的实例。

还有SignInAsync()

private async Task SignInAsync(User user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    var identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
    if (user.UserGroupId.IsSet())
        user.UserGroup = await _userManager.Load<UserGroup>(user.UserGroupId);

    //adding claims here ... //

    AuthenticationManager.SignIn(
        new AuthenticationProperties { IsPersistent = isPersistent }, 
        new CustomClaimsIdentity(identity));
}

AuthenticationManager 将被替换为 OwinSecurity


展示你的“登录”代码 :) - Andy Refuerzo
1
当然,没有任何公司会遇到内部威胁的问题cough斯诺登cough。至于你的问题,是的,这很容易。降低安全性总是容易的。我会想把每个人的密码都设置为空字符串并隐式使用它(快速而肮脏,但它会起作用,并同时表明您的安全性毫无价值)。如果您想要“正确”地做,可以子类化认证提供程序。 - Basic
@AndyRefuerzo:我已经添加了相关代码。 - Jeremy
@Basic:用户帐户和密码必须保持不变。普通的用户/密码登录页面应该保持原样。我所说的URL只是一个额外的后门。 - Jeremy
@Bjorn 如果您将用户帐户的密码设置为可以通过“神奇”URL绕过,那么您提供了一种虚假的安全感。这是最糟糕的系统设计。如果您无法说服老板这是一个不好的想法,请考虑与更具有风险意识(并且能力更强)的上级交谈。 - Basic
2个回答

107

您只需要使用usermanager按名称查找用户。如果有记录,则只需登录。

    public ActionResult StupidCompanyLogin()
    {

        return View();
    }

    [HttpPost]
    //[ValidateAntiForgeryToken] - Whats the point? F**k security 
    public async Task<ActionResult> StupidCompanyLogin(string name)
    {

        var user = await UserManager.FindByNameAsync(name);

        if (user != null)
        {

            await SignInManager.SignInAsync(user, true, true);
        }

        return View();
    }

43
超棒的动作名称! - Matt M
11
这并不像看上去的那样"愚蠢"。对于混合验证,您需要第二个网站以Windows用户身份登录,并将其凭据以某种方式传递给使用表单身份验证的网站。由于在Windows登录中,我们可能仅知道用户名,因此我们可以传递此用户名并强制使用仅有用户名的方式登录用户。添加一些加密和检查调用来自何处,或者尝试使用第二个Windows Auth应用程序设置的cookie可能有助于提高安全性。因此并不是那么"愚蠢"。 - user1228608
6
在我的情况下,需要实现一个“登录为”功能,让管理员可以以某个具体用户的身份访问部门门户网站。通过实现一个快速自定义的“登录为”密码检查,然后以该用户的身份登录而无需要求其明确提供密码,我能够轻松地完成这个任务,而不必深入研究自定义成员资格提供程序(尽管长期来看,自定义成员资格提供程序会是更加健壮的解决方案)。 - jleach
4
尽管这段代码令人不快,但它非常有用,可以在本地调试中模拟用户(只能锁定为DEBUG和localhost),包括完整的cookie等信息,以诊断特定于用户的问题,尤其是控制器级别的角色权限问题。 - Chris Moschini
1
如果我想让用户在点击电子邮件确认链接时无需密码即可登录,那么这仍然是一个“愚蠢的登录”吗?该链接包含由UserManager类生成的EmailConfirmationToken。 - Марк Павлович
显示剩余5条评论

0
对于那些从@heymega的帖子中收到错误信息的人,结果关键字是缺失的。简短而正确的答案是:
   var user = UserManager.FindByNameAsync(model.UserName).Result;
   try
   {
      await SignInManager.SignInAsync(user, isPersistent:
      false,rememberBrowser:false) ;
            
      return Json(new { success = true, message = "Success" });
   }
   catch (Exception ex)
   {
      return Json(new { success = false, message = "Wrong username" });
   } 

@heymega的回答是正确的。如果您等待调用,就不需要调用.Result。 - OJ Raqueño

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接