捕获登录事件,以便我可以缓存其他用户信息

时间:2017-04-11 10:29:21

标签: c# asp.net authentication owin asp.net-mvc-5.2

我已经构建了一个Web应用程序。当我建立它时,我勾选了“组织帐户”

效果很好 - 我使用Office 365帐户登录,User.Identity.Name包含电子邮件地址

此应用程序是旧版ASP Classic应用程序的替代前端。该应用程序有一个我需要使用的现有安全表。

我想使用电子邮件地址查找此表中的记录以获取

  • 用户的内部数据库密钥(因此我可以在数据库调用中使用它)

  • 用户的安全级别(授权)

我想在通过身份验证后立即查看,并将这两个值保存到Session以便稍后引用

我有一个现有的方法来执行所有这些查找和缓存。我实际上通过从_LoginPartial.cshtml视图调用它来实现它,但显然从视图中触发这种事情是不正确的

这是查找和缓存用户信息的代码。现在这是AccountController.cs,但不一定是

private Boolean GetAdditionalUserInfo()
{
    // if authentication info is saved, don't go find it
    if (Session["UID"] != null) return true;

    // get the db employee id from the database and save it to the session
    var r = (
            from e in db.Employees
            where e.Email == User.Identity.Name
            select new
            {
                e.Emp_ID,
                e.Group_ID
            }
            ).SingleOrDefault();

    if ((r == null) || (r.Group_ID == (int)Role.Inactive))
    {
        // couldn't find record or inactive
        return false;
    }

    // Update last login datetime
    Employee ell = db.Employees.Find(r.Emp_ID);
    ell.LastLogin = DateTime.Now;
    db.SaveChangesAsync();

    // Save user details to the session
    Session["UID"] = r.Emp_ID;
    // TBD: Investigate "CLAIMS" - this should probably be a claim
    Session["Role"] = r.Group_ID;

    return true;

}

我认为对User.Identity.Name的引用会触发登录过程,所以我可以尝试在启动时调用它(我不知道这样做的正确方法),或者我认为做正确的事情是使用OnAuthentication方法调用它,并将其链接起来我应该将我的函数名称传递给OnAuthenticated属性。这是方法和属性的两个链接:

https://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onauthentication(v=vs.118).aspx

https://msdn.microsoft.com/en-us/library/microsoft.owin.security.microsoftaccount.microsoftaccountauthenticationprovider.onauthenticated(v=vs.113).aspx

但我必须说OO编程不是我的事情,我无法从这些页面中找到如何使用它们或将它们放入哪个类。

page意味着需要进入Startup.Auth.cs,但我的Startup.Auth.cs看起来不像那个。这是我Startup.Auth.cs的大部分内容,当我在开始时勾选“组织”时,它主要是自动生成的。 (另一方面,app.UseKentorOwinCookieSaver();是我的下一个挑战,因为显然组织登录无法与Session一起使用,你能相信它吗!!!)

有人可以帮我添加所需的代码来致电GetAdditionalUserInfo()吗?登录后?或者确认我可以在启动时调用它,并建议正确的方法。

public partial class Startup
{
    private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
    private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
//private static string authority = aadInstance + tenantId;
// to make this multi tenant, use common endpoint, not the tenant specific endpoint
private static string authority = aadInstance + "common";

public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(
        CookieAuthenticationDefaults.AuthenticationType);

    // https://stackoverflow.com/questions/20737578/asp-net-sessionid-owin-cookies-do-not-send-to-browser
    app.UseKentorOwinCookieSaver();

    app.UseCookieAuthentication(
        new CookieAuthenticationOptions());

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            ClientId = clientId,
            Authority = authority,
            PostLogoutRedirectUri = postLogoutRedirectUri,
            TokenValidationParameters = new TokenValidationParameters
            {
                // If you don't add this, you get IDX10205
                // from here http://charliedigital.com/2015/03/14/adding-support-for-azure-ad-login-o365-to-mvc-apps/
                ValidateIssuer = false                        
            },
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                RedirectToIdentityProvider = ctx =>
                {
                    bool isAjaxRequest = (ctx.Request.Headers != null && ctx.Request.Headers["X-Requested-With"] == "XMLHttpRequest");

                    if (isAjaxRequest)
                    {
                        ctx.Response.Headers.Remove("Set-Cookie");
                        ctx.State = NotificationResultState.HandledResponse;
                    }

                    return System.Threading.Tasks.Task.FromResult(0);
                }
            }
        });
   }
}

1 个答案:

答案 0 :(得分:4)

在文章The OWIN OpenID Connect Middleware中,您可以找到有关如何使用Notifications的详细说明。在您的情况下,您应该订阅SecurityTokenValidated

RedirectToIdentityProvider = ctx => {...},
SecurityTokenValidated = (context) =>
{
    string userID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

    // Here you can retrieve information from Database. Let's say you get r.Group_ID.

    var role = r.Group_ID;

    // You can now add it to Identity and no need to use session.

    Claim roleClaim = new Claim(
        "http://nomatterwhatyouput/role",
        role,
        ClaimValueTypes.[RoleType],
        "LocalAuthority");
    context.AuthenticationTicket.Identity.AddClaim(roleClaim);

    // Do same for all values you have. Remember to set unique claim URL for each value.

    return Task.CompletedTask;
},

然后您可以在该文章中提到的操作中检索这些值:

public ActionResult Index()
{
    var role = ClaimsPrincipal.Current.FindFirst("http://nomatterwhatyouput/role");
    return View();
}