跨MVC 5和ASP.NET核心应用程序的基于Cookie的表单身份验证

时间:2015-06-18 07:23:09

标签: asp.net authentication asp.net-core asp.net-core-mvc formsauthentication

我已经在different sites使用了表单身份验证,甚至between different versions of .NET,但现在我们正在考虑在 ASP.NET 5(MVC 6)中启动一个新项目 ASP.NET Core,并希望在两者之间使用基于cookie的表单身份验证。登录在“旧”MVC 5应用程序中完成。

是否可以使用当前版本的ASP.NET 5来支持基于cookie的表单身份验证的某些跨应用程序配置? 这可以使用FormsAuthenticationModule MVC6 ASP.NET Core端实现,还是可以用新的authentication middleware以某种方式播放?还有其他建议吗?

3 个答案:

答案 0 :(得分:2)

过去几天我一直在为同样的问题敲打我的脑袋......但我已经解决了......(似乎是在坚持)

这是用于转换窗口和后来的窗体身份验证到窗体身份验证MVC5和MVC6所以希望您可以更改足够的代码以使其适用于您...我计划在重新编写登录脚本时更改某些部分。 (这是alpha所以会做出一些改变!)

我将以下代码放入我们的MVC5 Intranet站点以获取Windows身份验证的角色

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        // Get current windows Identity to get the roles out of it
        WindowsIdentity ident = WindowsIdentity.GetCurrent();

        string[] roles = new string[ident.Groups.Count];
        int i = 0;

        // get the groups from the current Identity
        foreach (var g in ident.Groups)
        {

            roles[i] = g.Translate(typeof(System.Security.Principal.NTAccount)).Value.ToString();
            i++;
        }

        // join into a single string  the roles that the user is a member of 
        string roleData = String.Join(";", roles) ;

        // create the forms ticket that all MVC5 sites with the same machine key will pick up.
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, ident.Name, DateTime.Now, DateTime.Now.AddMinutes(30), false, roleData, "/");
        string encTicket = FormsAuthentication.Encrypt(ticket);


        // add the user name first from the Principle and add Windows as this will come from Windows Auth
        roleData = ident.Name + ";" + "Windows;" + roleData;

        //use machine key to encrypt the data
        var encTicket2 = MachineKey.Protect(System.Text.Encoding.UTF8.GetBytes(roleData),
            "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware",
            "ApplicationCookie", "v1");

        //create a new cookie with a base64string of the encrypted bytes
        HttpCookie hc2 = new HttpCookie("cookie1", Convert.ToBase64String(encTicket2));
        hc2.Domain = ".domain.com";
        hc2.Expires = DateTime.Now.AddHours(8);
        Response.Cookies.Add(hc2);

        // NOTE: The name of the HttpCookie must match what the FormsAuth site expects.
        HttpCookie hc = new HttpCookie("cookie2", encTicket);
        hc.Domain = ".domain.com";
        hc.Expires = DateTime.Now.AddHours(8);
        Response.Cookies.Add(hc);
        // Ticket and cookie issued, now go to the FormsAuth site and all should be well.
        Response.Redirect("http://www.yoursite.com");
    }

这将在窗体和MVC6方法中创建一个Windows身份验证票证。

MVC6的字符串看起来像“John.Doe; Windows; Admin”

然后在MVC6启动文件中,我将以下代码放入配置部分......

        app.Use(async (context, next) =>
        {
            Logger _logger = new Logger("C:\\\\Logs\\Log.txt");
            try
            {

                var request = context.Request;
                var cookie = request.Cookies.Get("cookie1");
                var ticket = cookie.ToString();

                ticket = ticket.Replace(" ", "+");

                var padding = 3 - ((ticket.Length + 3)%4);
                if (padding != 0)
                    ticket = ticket + new string('=', padding);

                var bytes = Convert.FromBase64String(ticket);
                bytes = System.Web.Security.MachineKey.Unprotect(bytes,
                    "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware",
                    "ApplicationCookie", "v1");

                string ticketstring = System.Text.Encoding.UTF8.GetString(bytes);

                var ticketSplit = ticketstring.Split(';');

                var claims = new Claim[ticketSplit.Length];

                var OriginalIssuer = "";

                for (int index = 0; index != ticketSplit.Length; ++index)
                {

                    if (index == 0)
                    {
                        claims[index] = new Claim(ClaimTypes.Name, ticketSplit[index], "Windows");
                    }
                    else if (index == 1)
                    {
                        OriginalIssuer = ticketSplit[1];
                    }
                    else
                    {
                        claims[index] = new Claim(ClaimTypes.Role,ticketSplit[0], OriginalIssuer);
                    }
                }

                var identity = new ClaimsIdentity(claims, OriginalIssuer, ClaimTypes.Name,ClaimTypes.Role);

                var principal = new ClaimsPrincipal(identity);

                _logger.Write(principal.Identity.Name);

                context.User = principal;
                _logger.Write("Cookie End");
                await next();
            } catch (Exception ex)
            {
                _logger.Write(ex.Message);
                _logger.Write(ex.StackTrace);
            }
        });

然后获取cookie并从中创建新的声明标识。我只是完成了让它工作的逻辑,所以我确定它可以整理......只是想我会得到它,所以你可以看看你是否可以得到一些想法。

答案 1 :(得分:0)

WebForms不是ASP.NET 5的一部分。This is change #2 according to this blog post

<强>更新

ASP.NET MVC 6的新生命周期使用中间件来组合服务。您可以使用Security包进行身份验证,但不再支持旧的“表单”身份验证。

答案 2 :(得分:0)

这是我在Asp.net核心mvc中的简单代码,希望对此有所帮助:

Startup.cs 在功能ConfigureServices中,在services.AddAuthorization();

之后添加service.AddMvc()

在功能Configure中添加此类代码

app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationScheme = "UserLoginCookie",
                LoginPath = new PathString("/Account/Login"),
                AccessDeniedPath = new PathString("/Account/Forbidden"),
                AutomaticAuthenticate = true,
                AutomaticChallenge = true
            }); 

之前app.UseMvc....

在登录方法中: 像这样的核心代码:

     var claims = new List<Claim>()
        {
            new Claim(ClaimTypes.Name,userName here),
            new Claim("UserCodeInMyWebApp",Anything you want),
            new Claim(ClaimTypes.Role,"Admin")

        };
            var userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "UserLoginClaimsIdentity"));
            //signin
            await HttpContext.Authentication.SignInAsync("UserLoginCookie", userPrincipal, new AuthenticationProperties
            {
                ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
                IsPersistent = false,
                AllowRefresh = false
            });

            return RedirectToAction("AuthPage", "Home"); 

然后您可以通过键值访问声明值或检查是否经过身份验证:

bool flag = User.Identity.IsAuthenticated
 ClaimsIdentity user = User.Identity as ClaimsIdentity
 user.Name or user.FindFirst(the key value string you created).Value 

并检查如下:

  [HttpGet]
        [AllowAnonymous]
        public IActionResult Index()
        {
            return View();
        }

        [Authorize(Roles = "Admin")]
        [HttpGet]
        public IActionResult AuthPage()
        {
            return View();
        }

        public IActionResult About()
        {
            return View();
        }