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

Jef*_*inn 5 cookies asp.net-mvc-4

嗨,我正在尝试获取用户角色并将其设置为我的应用程序中的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);
    }
Run Code Online (Sandbox Code Playgroud)

我需要更改此项,因为我使用的是动态导航栏,根据用户角色显示不同的项目,并且在用户刷新页面之前它不会显示正确的导航栏.我认为这是因为视图使用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();
    }
Run Code Online (Sandbox Code Playgroud)

当我尝试这个时,看起来好像没有设置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;
    }
Run Code Online (Sandbox Code Playgroud)

Jef*_*inn 7

解决方案是 cookie 没有被添加到浏览器,因为我在 cookie 到达客户端之前重定向解决方案是让登录操作返回一个空白视图,然后从视图内部重定向到索引操作我的代码的最终版本如下注意:登录更改为 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();
    }
Run Code Online (Sandbox Code Playgroud)

和观点是。没有要显示的 HTML,因此重定向不明显。

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

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

  • 我对这个解决方案有点困惑。'Response.Redirect'不是仍然在服务器端执行吗?IE。从浏览器的角度来看,重定向还是一样吗? (2认同)