MVC4如何设置Cookie,然后重定向到操作 [英] MVC4 how do I set a cookie and then redirect to an action

查看:63
本文介绍了MVC4如何设置Cookie,然后重定向到操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获得用户角色,并将其设置为我的应用程序中的Cookie

Hi I am trying to get a users role and set it to a cookie in my application

我有以下有效的代码

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的同一操作中呈现的.

I need to change this because I am using a dynamic Navigation bar that shows different Items depending on the users role and it does not show the correct Nav bar until the user refreshes the page. I think this is because the view uses the cookie and the view is being rendered in the same action that sets the cookie.

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

I want to split this into 2 actions in my controller as follows

    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.不幸的是,由于第三方登录,我只能在生产环境的副本上测试此代码,因此调试信息有限.据我所知,问题似乎出在我如何重定向.

When I try this it looks like the Cookie hasn't been set. Unfortunately I can only test this code on a replication of our Production Environment because of the 3rd party login so I have limited debug info. As far as I can tell the problem seems to be with how I am redirecting.

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

I have provided the methods I use cor creating the cookie and assigning the roles bellow.

其他信息

    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;
    }

推荐答案

此解决方案是未将cookie添加到浏览器,因为我在cookie到达客户端之前进行了重定向,因此解决方案是登录操作返回一个空白视图,然后从该视图内部重定向到索引操作,最终代码的最终版本如下所示:注意:登录已更改为AuthenticateUser

The solution to this was that the cookie wasn't being added to the browser because I was redirecting before the cookie reached the client side the solution was to have the Login Action return a blank view and then from inside the view redirect to the Index action the final version of my code ended up as follows NOTE: Login changed to 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,因此重定向不会引起注意.

and the view is. There is no HTML to display so the redirect is not noticeable.

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

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

This code is checking that there is a cookie and that the user data isn't empty, if theses checks pass it shows the user the home page. Otherwise it redirects to the authentication action that gets the email address that was set in the browser by our 3rd party central login software and gets the users details from the users details. If the user is not in our user table they are given basic access rights.

这篇关于MVC4如何设置Cookie,然后重定向到操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆