GetExternalLoginInfoAsync返回空MVC

时间:2019-12-30 22:53:51

标签: asp.net-mvc visual-studio azure

当尝试使用Microsoft AD从本地主机运行我的MVC应用程序时,收到以下代码错误。在调试应用程序时,我注意到GetExternalLoginInfoAsync返回null。但是,该应用程序可以在网络上正常运行。我想念什么?有人请帮忙。我已将我的代码发布在错误消息下方。


“ /”应用程序中的服务器错误。

对象引用未设置为对象的实例。   说明:执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪,以获取有关错误及其在代码中起源的更多信息。

异常详细信息:System.NullReferenceException:对象引用未设置为对象的实例。

源错误:

第140行:{ 141行:ExternalLoginInfo loginInfo =等待AuthenticationManager.GetExternalLoginInfoAsync(); 第142行:ClaimsIdentity ClaimsIdentity = loginInfo.ExternalIdentity; 第143行:ApplicationUser applicationUser =新的ApplicationUser(claimsIdentity);

第144行:IdentityResult结果=等待UserManager.PersistAsync(applicationUser);

我的代码:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using SampleQuoteTracker.Models;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;


namespace SampleQuoteTracker.Controllers
{
    /// <summary>
    /// Provides methods for accepting and desplaying account authenication and creating new accounts.
    /// </summary>
    public class AccountController : Controller
    {
        //
        // GET: /Account/Login
        public ActionResult Login(string returnUrl)
        {
            ViewBag.Title = "Log In";
            LoginViewModel loginViewModel = new LoginViewModel()
            {
                ReturnUrl = returnUrl
            };
            return View(loginViewModel);
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<JsonResult> Login(LoginViewModel model)
        {
            // seed return object optimistically
            AjaxResultModel loginResult = new AjaxResultModel
            {
                Status = "Valid",
                ReturnUrl = GetLocalUrl(model.ReturnUrl),
                Message = null
            };
            if (Request.IsAjaxRequest())
            {
                if (!ModelState.IsValid)
                {
                    loginResult.Status = "Invalid";
                    loginResult.Message = Tools.ListModelStateErrors(ModelState);
                }
                if (loginResult.Status == "Valid")
                {
                    SignInStatus result = await SignInManager.PasswordSignInAsync(
                        model.Email,
                        model.Password,
                        model.RememberMe,
                        shouldLockout: false);
                    switch (result)
                    {
                        case SignInStatus.Success:
                            loginResult.Status = "Success";
                            break;
                        case SignInStatus.LockedOut:
                            loginResult.Status = "LockOut";
                            loginResult.Message = AlertMessages.AccountLockOut;
                            break;
                        case SignInStatus.Failure:
                        default:
                            loginResult.Status = "Failure";
                            loginResult.Message = AlertMessages.AuthenticationFailure;
                            break;
                    }
                }
            }
            return Json(loginResult);
        }

        //
        // POST: /Account/LogOff
        [Authorize]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LogOff()
        {
            //AuthenticationManager.SignOut();
            //return RedirectToAction("SignOutCallback");
            return null;
        }

        public void SignIn(string returnUrl = "/")
        {
            if (returnUrl == "/")
            {
                returnUrl = Request.ApplicationPath;
            }
            Uri baseUri = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port).Uri;
            Uri uri = new Uri(baseUri, returnUrl);
            // If this action is called and the user is already authenticated,
            // it means the user is not a member of the appropriate role for
            // the controller/action requested.
            if (Request.IsAuthenticated)
            {
                RouteValueDictionary values = RouteDataContext.RouteValuesFromUri(uri);
                string controllerName = (string)values["controller"];
                string actionName = (string)values["action"];
                string errorUrl = Url.Action("Error",
                    routeValues: new
                    {
                        message = "You are not authorized to view this content",
                        controllerName,
                        actionName
                    });
                Response.Redirect(errorUrl, true);
            }
            else
            {
                // https://stackoverflow.com/a/21234614
                // Activate the session before login to generate the authentication cookie correctly.
                Session["Workaround"] = 0;
                // Send an OpenID Connect sign-in request.
                string externalLoginCallback = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
                AuthenticationManager.Challenge(new AuthenticationProperties { RedirectUri = externalLoginCallback },
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);
            }
        }

        //public IAuthenticationManager AuthenticationManager
        //{
        //    get { return HttpContext.GetOwinContext().Authentication; }

        //}

        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            ClaimsIdentity claimsIdentity = loginInfo.ExternalIdentity;
            ApplicationUser applicationUser = new ApplicationUser(claimsIdentity);
            IdentityResult result = await UserManager.PersistAsync(applicationUser);
            if (result.Succeeded)
            {
                claimsIdentity = await applicationUser.GenerateUserIdentityAsync(UserManager);
            }
            AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = false }, claimsIdentity);
            return Redirect(returnUrl);
        }


        [Authorize]
        public void SignOut()
        {
            string callbackUrl = Url.Action("SignOutCallback", "Account", null, Request.Url.Scheme);
            AuthenticationProperties properties = new AuthenticationProperties { RedirectUri = callbackUrl };

            AuthenticationManager.SignOut(
                properties,
                OpenIdConnectAuthenticationDefaults.AuthenticationType,
                CookieAuthenticationDefaults.AuthenticationType,
                Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
        }

        public ActionResult Error(string message, string controllerName = "Account", string actionName = "SignIn")
        {
            Exception exception = new Exception(message);
            HandleErrorInfo handleErrorInfo = new HandleErrorInfo(exception, controllerName, actionName);
            return View("Error", handleErrorInfo);
        }
        public ActionResult SignOutCallback()
        {
            if (Request.IsAuthenticated)
            {
                // Redirect to home page if the user is authenticated.
                return RedirectToAction("Index", "Home");
            }

            return View();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && UserManager != null)
            {
                UserManager.Dispose();
                UserManager = null;
            }
            base.Dispose(disposing);
        }
        #region Helpers
        private ApplicationSignInManager _signInManager;
        private ApplicationUserManager _userManager;
        private IAuthenticationManager _authenticationManager;
        // Used for XSRF protection when adding external logins
        private const string XsrfKey = "XsrfId";
        /// <summary>
        /// Gets a reference to the <see cref="ApplicationSignInManager"/>.
        /// </summary>
        protected ApplicationSignInManager SignInManager
        {
            get
            {
                return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
            }
            private set { _signInManager = value; }
        }
        protected ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }
        protected IAuthenticationManager AuthenticationManager
        {
            get
            {
                return _authenticationManager ?? HttpContext.GetOwinContext().Authentication;
            }
            private set
            {
                _authenticationManager = value;
            }
        }
        /// <summary>
        /// Ensures the <paramref name="returnUrl"/> belongs to this application.
        /// <para>We don't want to redirect to a foreign page after authentication.</para>
        /// </summary>
        /// <param name="returnUrl">a <see cref="System.String"/> containing the page address that required authorization.</param>
        /// <returns>a <see cref="System.String"/> containing a local page address.</returns>
        private string GetLocalUrl(string returnUrl)
        {
            if (!Url.IsLocalUrl(returnUrl))
            {
                return Url.Action("Index", "Home");
            }
            return returnUrl;
        }
        private class ChallengeResult : HttpUnauthorizedResult
        {
            public ChallengeResult(string provider, string redirectUri)
                : this(provider, redirectUri, null)
            {
            }

            public ChallengeResult(string provider, string redirectUri, string userId)
            {
                LoginProvider = provider;
                RedirectUri = redirectUri;
                UserId = userId;
            }

            public string LoginProvider { get; set; }
            public string RedirectUri { get; set; }
            public string UserId { get; set; }

            public override void ExecuteResult(ControllerContext context)
            {
                var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
                if (UserId != null)
                {
                    properties.Dictionary[XsrfKey] = UserId;
                }
                context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
            }
        }
        private class RouteDataContext : HttpContextBase
        {
            public override HttpRequestBase Request { get; }

            private RouteDataContext(Uri uri)
            {
                string url = uri.GetLeftPart(UriPartial.Path);
                string qs = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);

                Request = new HttpRequestWrapper(new HttpRequest(null, url, qs));
            }

            public static RouteValueDictionary RouteValuesFromUri(Uri uri)
            {
                return RouteTable.Routes.GetRouteData(new RouteDataContext(uri)).Values;
            }
        }
        #endregion
    }
}

1 个答案:

答案 0 :(得分:0)

最终,当Owin中间件检查上下文时,将删除ExternalCookie。 这样,AuthenticationManager.GetExternalLoginInfo()登录后返回null,保存该信息的cookie被删除,并由ApplicationCookie代替。

因此,在您的Startup.cs中添加以下内容

public void ConfigureAuth(IAppBuilder app)
{
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Enable the application to use a cookie to store information for the signed in user
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/LogOn")
    });
    ....
}

有关更多详细信息,您可以参考此article