当尝试使用Microsoft AD从本地主机运行我的MVC应用程序时,收到以下代码错误。在调试应用程序时,我注意到GetExternalLoginInfoAsync返回null。但是,该应用程序可以在网络上正常运行。我想念什么?有人请帮忙。我已将我的代码发布在错误消息下方。
“ /”应用程序中的服务器错误。
对象引用未设置为对象的实例。 说明:执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪,以获取有关错误及其在代码中起源的更多信息。
异常详细信息:System.NullReferenceException:对象引用未设置为对象的实例。
源错误:
第140行:{ 141行:ExternalLoginInfo loginInfo =等待AuthenticationManager.GetExternalLoginInfoAsync(); 第142行:ClaimsIdentity ClaimsIdentity = loginInfo.ExternalIdentity; 第143行:ApplicationUser applicationUser =新的ApplicationUser(claimsIdentity);
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
}
}
答案 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。