首页 > 解决方案 > 可以为一个 Api 设置两个身份验证吗?身份服务器4

问题描述

我建立了一个身份服务器,并与一个客户端两个grant_types。混合和密码。

现在,他们每个人都可以独立获取访问令牌。如果同时添加它们。只是混合工作。密码模式可以获得访问令牌,但是当访问带有不记名令牌的 api 时。我被重定向到混合登录页面。

 // add password authentication
 services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
         options.Authority = "http://localhost";
         options.RequireHttpsMetadata = false;

         options.Audience = "SlideCloudStorage";
     });
 // add hybrid authentication
 // todo add this information to configuration.
 services.AddAuthentication(
       options =>
       {
           options.DefaultScheme = "Cookies";
           options.DefaultChallengeScheme = "oidc";
       })
    .AddCookie("Cookies")
    .AddOpenIdConnect(
         "oidc",
         options =>
         {
             options.SignInScheme = "Cookies";
             options.Authority = "http://localhost";
             options.RequireHttpsMetadata = false;

             options.ClientId = "slide-cloud-storage";
             options.ClientSecret = "secret";
             options.ResponseType = "code id_token";

             options.SaveTokens = true;
             options.GetClaimsFromUserInfoEndpoint = true;

             options.Scope.Add("offline_access");
             options.ClaimActions.MapJsonKey("website", "website");
           });

希望这不是 XY 问题。为什么我要添加两个身份验证?

密码模式适用于我的桌面客户端。Hybrid 适用于我的网络/移动客户端。

标签: c#asp.net-coreidentityserver4

解决方案


services.AddAuthentication("Bearer")

这会将默认身份验证方案设置为Bearer

services.AddAuthentication(
    options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    })

这会将默认身份验证方案设置为Cookies(并将默认质询方案设置为oidc)。所以在此之后,默认情况下不再调用承载认证。

配置多个身份验证方案非常好,在许多情况下也有些需要。但是您必须了解,框架会自动调用一个默认值(对于每个身份验证操作)。我已经对这个问题进行了更详细的解释,但这个想法基本上是当你不做任何特别的事情时,当请求进来时,默认的身份验证方案将用于对用户进行身份验证。

因此,在您的情况下,Cookies作为默认方案,用户将尝试通过他们的 cookie 登录。对于以用户为中心的应用程序来说,这通常是一个很好的默认设置,因为大多数用户都会使用 cookie 来验证自己的身份。另一方面,对这些应用程序的 API 访问更为特殊,通常仅限于几个控制器或路由;因此,将不记名身份验证作为默认设置通常没那么有用。

那么什么时候Cookies是默认的,并且只能有一个默认会自动调用,那么使用其他方案的方法是什么?答案是授权策略。

授权策略通常允许您根据某些规则限制访问。策略基本上是这些规则的集合。出于授权目的,您通常会检查声明值以控制某人是否被授权做某事。然而,授权策略还有另一个方面,那就是它们允许您将身份验证方案指定为规则。

当您使用 来创建授权策略时AuthorizationPolicyBuilder,您可以指定它所需的身份验证方案。当授权策略随后用于授权请求时,如果这些方案尚未经过身份验证它将自动对其进行身份验证。

因此,您可以使用此机制为您的 API 控制器触发不记名身份验证,而不会影响默认 cookie 身份验证,只要您不指定任何其他内容,就会使用该身份验证。

[Authorize("ApiPolicy")]
public class MyApiController : ControllerBase
{
    // …
}

Startup.ConfigureServices

services.AddAuthorization(options =>
{
    var apiPolicy = new AuthorizationPolicyBuilder("Bearer")
        .RequireAuthenticatedUser()
        .Build();
    options.AddPolicy("ApiPolicy", apiPolicy);
});

有了这个,您配置了一个自定义策略,您可以随时扩展它以添加其他要求(例如特殊声明),并且您正在使用它来授权客户端访问您的 API。

如果您只需要少数操作或控制器,您还可以直接在[Authorize]属性中指定身份验证方案。这使您不必创建自定义授权策略,但另一方面,如果您想通过其他要求(或更改身份验证方案)扩展您的策略,当然需要更多的复制和维护:

[Authorize(AuthenticationSchemes = "Bearer")] 
public class MyApiController : ControllerBase
{
    // …
}

请注意,最后,这也会导致临时创建一个策略来授权用户。所以效果和底层机制其实是一样的。


推荐阅读