同时验证Asp.Net核心2.0 MVC应用程序(cookie)和REST API(JWT)

时间:2017-11-22 14:41:36

标签: reactjs authentication cookies jwt asp.net-core-2.0

我正在使用VS 2017 Asp.Net Core 2.0 Web应用程序模板,以及React.js模板选项。

这给了我一个基本的MVC + React设置: 1.承载React应用程序的单个MVC页面 2. React应用程序的ClientApp文件夹 3. React应用程序所讨论的Rest API。

默认情况下,这些都没有经过身份验证。我想要保护MVC页面和REST API。

我修改了代码,以便对MVC页面使用cookie身份验证,对REST API使用JWT承载身份验证。

对于MVC cookie身份验证,我有一个MVC登录登录表单。这很好。

对于REST API身份验证,我添加了一个接收用户名和登录名的TokensController,并生成一个JWT令牌,用于对REST API的请求。从Postman测试时,这也可以正常工作:如果用户如果用户尝试访问没有有效JWT令牌的REST API,则用户获得401响应。如果用户从TokensController获取令牌并使用它来访问REST API,则用户获得200响应。

我的问题是将这两者结合起来。我想要的是,当未经身份验证的用户访问我的MVC页面时,用户将被重定向到登录表单。提交该表单时,用户将通过MVC应用程序(获取cookie)和REST API(获取JWT令牌)进行身份验证。

我尝试实现这一点,以便不使用MVC登录页面,而是使用React登录组件,未经身份验证的用户将被重定向到该页面。在提交React登录表单时,在React onSubmit事件中,我首先调用TokensController获取JWT令牌,将该令牌存储在浏览器localStorage中,然后将表单提交给MVC控制器以进行cookie登录。

我无法让MVC重定向到我的React登录组件。可能是我不了解的一些客户端与服务器端路由问题。

在routes.tsx中,我将我的React登录组件设置为此路由:

<Route path='/login' component={Login} />

在Startup.cs中,我有这个:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        // Cookie auth for MVC page that hosts React app
        .AddCookie(options =>
            {
                options.LoginPath = new PathString("/Account/Login");
                options.LogoutPath = new PathString("/Account/Logout");

                options.Cookie = new CookieBuilder
                {
                    HttpOnly = true,
                    Name = "OurCookieAuthentication",
                    Path = "/",
                    SameSite = SameSiteMode.Lax,
                    SecurePolicy = CookieSecurePolicy.SameAsRequest
                };
                options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                options.SlidingExpiration = true;

            }
        )
        // JWT authenticaton for REST API called by React app
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = false,
                ValidateIssuer = false,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("thesecret")),
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromMinutes(5)
            };
        });
    ;

    services.AddMvc()
}

上面,这个指向我的MVC登录页面,它适用于cookie登录,但不处理JWT:

options.LoginPath = new PathString("/Account/Login");

如果我在尝试重定向到我的React登录组件时将其更改为此,则它不起作用(我的React组件未加载,可能是因为请求转到&#34; / login&#34; path on服务器MVC控制器而不是我的客户端React组件):

options.LoginPath = new PathString("/login");

关于如何才能最好地实现我之后的想法?

1 个答案:

答案 0 :(得分:0)

您是否尝试过将反应视图添加到MVC AccountController中,如下所示:

public IActionResult Login()
{
    return View("../Home/Index"); //this should be the cshtml view that serves up the spa
}

然后在您的反应路线中将登录路线更改为:

    <Route path='/Account/Login' component={Login} />