ChatGPT解决这个技术问题 Extra ChatGPT

一起使用不记名令牌和 cookie 身份验证

我有一个单页应用程序 - 或多或少基于 MVC5 SPA 模板 - 使用不记名令牌进行身份验证。

该站点还有几个需要保护的传统 MVC 页面,但使用 cookie 身份验证。

在 Startup.Auth 我可以启用两种类型的授权:

app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOAuthBearerTokens(OAuthOptions);

但是,这似乎有一个副作用,因为每当从 SPA 发送 AJAX 请求时,它都会发送标头中的不记名令牌和 cookie。

而我真正想要的行为是只有承载令牌用于 WebAPI 调用,只有 cookie 用于 MVC 调用。

我还希望 MVC 调用在未授权时重定向到登录页面(设置为 CookieAuthenticationOption),但显然我不希望在进行 API 调用时发生这种情况。

有没有办法在一个应用程序中进行这种类型的混合模式身份验证?也许通过路径/路由过滤器?


A
Appetere

我想我解决了这个问题:-

Startup.Auth 正在连接 OWIN 管道,因此在其中包含 Cookie 和令牌是正确的。但是对 cookie 选项的一项更改指定了它应该应用于的身份验证类型:

CookieOptions = new CookieAuthenticationOptions
{
  AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie   
};

然后我需要将 WebAPI 配置为仅使用令牌:

public static void Configure(HttpConfiguration config)
{
   // Configure Web API to use only bearer token authentication.
   config.SuppressDefaultHostAuthentication();
   config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
}

这似乎达到了我想要的。 WebAPI 只使用不记名令牌而不使用 cookie,一些传统的 MVC 页面在登录后使用 cookie(使用 AuthenticationManager)。


史蒂夫,我也会做同样的事情。我担心的一个问题是 cookie 和令牌(即本地存储)不同步。换句话说,cookie 和 token 是否需要同时过期,或者是否有一种机制可以在其中一个或另一个丢失时优雅地处理?
顺便说一句,CookieAuthenticationOptions 中还有一个名为“CookieHttpOnly”的选项,它将阻止 JavaScript 将 cookie 传递给您的 API。
@Steve,只想澄清一件事。您是否在 SPA 和 MVC 部分中使用单独的登录页面?或者您可以通过单一登录页面实现这一目标?如果是case你怎么做?
@ThisGuy 这是不正确的。 “CookieHttpOnly”只会阻止 cookie 的值在 JavaScript 中被读取,它不会阻止在 AJAX 请求上发送 cookie。
对于那些想知道为什么找不到 SuppressDefaultHostAuthentication() 和 HostAuthenticationFilter 的人:您需要安装此软件包:通过 nuget:Install-Package Microsoft.AspNet.WebApi.Owin
N
Nick Cox

您可以在 http-only 模式下将 jwt 令牌添加到 cookie(这里我的 jwt 令牌 cookie 名称是“access_token”),并制作这样的中间件

public class JwtCookieMiddleware
{
    private readonly RequestDelegate _next;

    public JwtCookieMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext ctx)
    {
        if (ctx.Request.Cookies.TryGetValue("access_token", out var accessToken))
        {
            if (!string.IsNullOrEmpty(accessToken))
            {
                string bearerToken = String.Format("Bearer {0}", accessToken);
                ctx.Request.Headers.Add("Authorization",bearerToken);
            }
        }
        return this._next(ctx);
    }
}
public static class JwtCookieMiddlewareExtensions
{
    public static IApplicationBuilder UseJwtCookie(this IApplicationBuilder build)
    {
        return build.UseMiddleware<JwtCookieMiddleware>();
    }
}

你需要像这样在启动时使用中间件:

app.UseJwtCookie();
app.UseAuthentication();
app.UseMvc();

如果此请求带有令牌 cookie,则上述代码会将 jwt 令牌添加到 http 请求标头;


我相信问题不在于 asp.net core