在MVC 5中使用Owin在浏览器中未设置身份验证cookie

时间:2014-10-15 06:48:06

标签: asp.net-mvc authentication owin

这是我刚刚努力奋斗的事情,我现在有了答案,所以我会问这个并回答这个问题。

问题是由于我在新的MVC 5站点上设置了身份验证,该站点与现有的非常自定义的成员资格数据库集成。

我基本上需要复制FormsAuthentication功能以让用户登录会话。除了普通的用户名/密码方法外,该系统还具有自动登录功能,该功能使用网址中的键/值。

我将控制器代码拆分如下​​:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginViewModel model, string returnUrl)
    {                           
        if (ModelState.IsValid)
        {
            var loginResult = _authenticationService.Login(model.Email, model.Password, returnUrl);

            if (loginResult.Succeeded)
            {
                _loginFacade.DoLogin(loginResult, model.RememberMe);
            }
            else
            {
                ModelState.AddModelError("", "Invalid username or password.");
            }
        }

        return View(model);
    }

    [AllowAnonymous]
    public ActionResult Autologin(string key, string value)
    {

        if (ModelState.IsValid)
        {
            var loginResult = _authenticationService.AutoLogin(key, value);

            if (loginResult.Succeeded)
            {
                _loginFacade.DoLogin(loginResult, false);
            }
            else
            {
                ModelState.AddModelError("", "error message goes here");
            }
        }

        return View("Login");
    }

对_authenticationService.Login的调用很好。那里没问题。

在对DoLogin的调用中,我正在做各种事情来创建身份验证属性,然后能够在新用户中签名,但无论我做什么,用户都不会在浏览器中登录:< / p>

public void DoLogin(LoginResult<Agent> loginResult, bool rememberMe)
    {
        string redirectUrl;
        if (loginResult.Succeeded)
        {
            var claimsIdentity = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, loginResult.User.Email),     
                new Claim(ClaimTypes.Role, "User"),
                new Claim(ClaimTypes.NameIdentifier, loginResult.User.Id.ToString()),
                new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", loginResult.User.Id.ToString())
            }, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);

            var authProperties = new AuthenticationProperties
            {
                IsPersistent = rememberMe,
            };
            if (rememberMe)
            {
                authProperties.ExpiresUtc = DateTime.UtcNow.AddMonths(1);
            }
            authProperties.Dictionary.Add("Id", loginResult.User.Id.ToString());

            var authentication = _context.GetOwinContext().Authentication;
            authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
            authentication.SignIn(authProperties, claimsIdentity);

            DoStuff();
            redirectUrl = GetRedirectUrl();
        }
        else
        {
            redirectUrl = GetOtherRedirectUrl();
        }
        _context.Response.Redirect(redirectUrl, true);
    }

我会将解决方案作为答案发布

1 个答案:

答案 0 :(得分:7)

当我跳过Response.Redirect行时,发生了答案的初步线索。代码在那种情况下起作用。

基本上,

        _context.Response.Redirect(redirectUrl, true);

需要

        _context.Response.Redirect(redirectUrl, false);

与FormsAuthentication(在编写身份验证代码时实际设置cookie)不同,AuthenticationManager会创建AuthenticationResponseGrant或AuthenticationResponseRevoke对象。

因此,在调用authentication.SignIn(authProperties,claimsIdentity)时,不会设置身份验证cookie。它们稍后被调用,因此使用Response.Redirect结束响应将在将cookie添加到响应对象之前终止该线程。通过将endResponse参数更改为false,cookie将按预期应用于响应对象。