MVC4如何设置cookie然后重定向到一个动作

时间:2014-01-13 11:56:15

标签: asp.net-mvc-4 cookies

您好我正在尝试获取用户角色并将其设置为我的应用程序中的cookie

我有以下代码可以使用

public ActionResult Index()
    {
        var user = User.Identity.Name;  // set by 3rd party central login in manager

        // key to check that we are in our environment with 3rd party login set up
        if (ConfigurationManager.AppSettings["IsNGDC"] == "true")
        {
            // ActiveKey login
            if (user.Contains("uid="))
            {
                var endIndex = user.IndexOf(",ou");

                var userEmail = user.Substring(4, endIndex - 4);
                user = userEmail;
            }

            SetAuthenticationCookie(user);
        }

        // view model is not needed I could just pass in a string
        var viewModel = new SiteminderViewModel { Username = user };

        if (ModelState.IsValid)
        {
            this.AssignRoles(viewModel);
            return this.View();
        }

        return View(viewModel);
    }

我需要更改此项,因为我使用的是动态导航栏,根据用户角色显示不同的项目,并且在用户刷新页面之前它不会显示正确的导航栏。我认为这是因为视图使用cookie并且视图是在设置cookie的同一动作中呈现的。

我想在控制器中将其分为2个动作,如下所示

    public void LogIn()
    {
        var user = User.Identity.Name;  // set by 3rd party central login in manager

        // key to check that we are in our environment with 3rd party login set up
        if (ConfigurationManager.AppSettings["IsNGDC"] == "true") 
        {
            // ActiveKey login
            if (user.Contains("uid="))
            {
                var endIndex = user.IndexOf(",ou");

                var userEmail = user.Substring(4, endIndex - 4);
                user = userEmail;
            }

            SetAuthenticationCookie(user);
        }

        // view model is not needed I could just pass in a string
        var viewModel = new SiteminderViewModel { Username = user };

        this.AssignRoles(viewModel);

        // default URL in Index action for this controller
        this.Response.Redirect(FormsAuthentication.DefaultUrl, false);
    }

    public ActionResult Index()
    {
        ViewBag.Message = "Home App Description here";
        return this.View();
    }

当我尝试这个时,看起来好像还没有设置Cookie。不幸的是,由于第三方登录,我只能在复制生产环境时测试此代码,所以我的调试信息有限。据我所知,问题似乎与我如何重定向有关。

我提供了使用cor创建cookie并分配角色的方法。

其他信息

    private void SetAuthenticationCookie(string username)
    {
        var tkt = new FormsAuthenticationTicket(1, username, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(20), true, string.Empty);
        var encryptedTkt = FormsAuthentication.Encrypt(tkt);

        var formsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTkt);
        this.Response.Cookies.Add(formsCookie);
    }

    private void AssignRoles(SiteminderViewModel viewModel)
    {
        var authCookie = System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        var ticket = authCookie != null ? FormsAuthentication.Decrypt(authCookie.Value) : new FormsAuthenticationTicket(1, viewModel.Username, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(20), true, string.Empty);
        var user = this.userRepository.GetUser(viewModel.Username);

        if (user != null)
        {
            var principleProperties = new PrincipleProperties(ticket.UserData)
            {
                UserName = user.Email,
                UserRole = user.UserGroup.Role.Name.Replace(" ", string.Empty),
                ContextId = contextRepository.GetContextByDataOwnerGroupId(user.UserGroupId)
            };

            if (user.DeletedIndicator)
            {
                principleProperties.UserRole = string.Empty;
            }

            this.SetPrinciple(ticket, principleProperties);
        }
    }

    private FormsAuthenticationTicket SetPrinciple(FormsAuthenticationTicket ticket, PrincipleProperties properties)
    {
        var newticket = new FormsAuthenticationTicket(
            ticket.Version,
            ticket.Name,
            ticket.IssueDate,
            ticket.Expiration,
            ticket.IsPersistent,
            properties.Serialize(),
            ticket.CookiePath);

        var encryptedTkt = FormsAuthentication.Encrypt(newticket);

        var formsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTkt);
        this.Response.Cookies.Set(formsCookie);

        var referenceDataIdentity = new ReferenceDataIdentity(ticket);
        var principle = new ReferenceDataPrinciple(referenceDataIdentity, properties);

        Thread.CurrentPrincipal = principle;
        return newticket;
    }

1 个答案:

答案 0 :(得分:4)

解决这个问题的原因是cookie没有被添加到浏览器,因为我在cookie到达客户端之前重定向,解决方案是让Login Action返回一个空白视图,然后从视图内部重定向到索引操作我的代码的最终版本最终如下注意:登录更改为AuthenticateUser

    public ActionResult Index()
    {
        var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            var ticket = FormsAuthentication.Decrypt(authCookie.Value);

            if (ticket != null && ticket.UserData != string.Empty)
            {
                return this.View();
            }
        }

        return RedirectToAction("AuthenticateUser");
    }

    public ActionResult AuthenticateUser()
    {
        // set by Site minder
        var user = User.Identity.Name;

        // ActiveKey login
        if (user.Contains("uid="))
        {
            var endIndex = user.IndexOf(",ou");

            var userEmail = user.Substring(4, endIndex - 4);
            user = userEmail;
        }

        SetAuthenticationCookie(user);


        var viewModel = new SiteminderViewModel { Username = user };

        this.AssignRoles(viewModel);
        return this.View();
    }

并且视图是。没有要显示的HTML,因此重定向不明显。

@{
    ViewBag.Title = "AuthenticateUser";
    Layout = null;
    Response.Redirect( Url.Action("Index", "Home"), false);
}

此代码检查是否存在cookie并且用户数据不为空,如果这些检查通过,则向用户显示主页。否则,它会重定向到身份验证操作,该操作将获取我们的第三方中央登录软件在浏览器中设置的电子邮件地址,并从用户详细信息中获取用户详细信息。如果用户不在我们的用户表中,则他们将获得基本访问权限。