同时对 Asp.Net core 2.0 MVC 应用程序 (cookie) 和 REST API (JWT) 进行身份验证
Posted
技术标签:
【中文标题】同时对 Asp.Net core 2.0 MVC 应用程序 (cookie) 和 REST API (JWT) 进行身份验证【英文标题】:Authenticating to Asp.Net core 2.0 MVC application (cookie) and REST API (JWT) simultaneously 【发布时间】:2018-05-06 08:28:21 【问题描述】:我正在使用带有 React.js 模板选项的 VS 2017 Asp.Net Core 2.0 Web 应用程序模板。
这给了我一个基本的 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 令牌)的身份验证。
我试图实现这一点,这样我将拥有一个 React 登录组件,而不是使用 MVC 登录页面,并且未经身份验证的用户将被重定向到该页面。在提交 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 组件未加载,可能是因为请求转到服务器 MVC 控制器上的“/login”路径而不是我的客户端 React 组件):
options.LoginPath = new PathString("/login");
关于如何最好地实现我所追求的任何想法?
【问题讨论】:
您的 React 页面是与 ASP Core 项目捆绑在一起还是单独运行? IE。项目在 localhost:8080 下运行,react 项目在 localhost:8088 下运行 我使用的是 VS 2017 Asp.Net Core React 模板,所以 REST API、MVC 主机页面和 React 应用程序都在同一个 VS 项目中,并且在同一个 http 端口上。 React 应用程序及其 MVC 主机页面位于根目录 localhost:32264,而 REST API 位于同一端口 localhost:32264/api。一旦我掌握了基础知识,我会将 REST API 移动到单独的 VS 项目中以方便维护。 【参考方案1】:您是否尝试过像这样将反应视图添加到 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 />
【讨论】:
以上是关于同时对 Asp.Net core 2.0 MVC 应用程序 (cookie) 和 REST API (JWT) 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core 2.0 MVC 6. 如何管理每个视图的javascript文件?
ASP.NET Core 2.0/Razor Pages - 如何在请求之间将数据保存在 NonFactors MVC6 网格中?