IS4 MVC 多 API 通信问题

问题描述 投票:0回答:0

我正在重构一个单一的 .NET CORE MVC 应用程序。到目前为止我所拥有的是我添加了 IS4 并将部分逻辑从 MVC 提取到新的 API。 这就是我设置 IS4

的方式
public static IEnumerable<ApiScope> GetApiScopes() =>
    new List<ApiScope> 
    {
        new ApiScope("CRMApi", "CRM API Scopes"),                
    };
public static IEnumerable<ApiResource> GetApiResources() =>
    new List<ApiResource>
    {
        new ApiResource("CRMApi", "CRM API Resources")
        {
            Scopes = { "CRMApi" },
            Enabled = true,
            UserClaims = { "sub", "name", "email" },
        },
    };
public static IEnumerable<Client> GetClients() =>
    new List<Client>
    {
       new Client
       {
           ClientId = "CRMClientMVC",
           ClientName = "MVC Client",
           ClientSecrets = { new Secret("MVCSecret".Sha512()) },
           AllowedGrantTypes = GrantTypes.Hybrid,
           RequirePkce = false,
           AllowedScopes = {
               IdentityServerConstants.StandardScopes.OpenId,
               IdentityServerConstants.StandardScopes.Profile,
               IdentityServerConstants.StandardScopes.Email,
               "CRMApi",
           },
           RedirectUris = new List<string>{ $"{Discovery.CRMClient}/signin-oidc" },
           PostLogoutRedirectUris = new List<string> { $"{Discovery.CRMClient}/signout-callback-oidc" }
       },
       new Client
        {
            ClientId = "CRMNewApi",
            ClientName = "CRM API",
            ClientSecrets = { new Secret("CRMApi.secret".Sha256()) },
            AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
            RequirePkce = false,
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                "CRMApi",
            },                    
            AlwaysIncludeUserClaimsInIdToken = true
        },
    };

我的MVC

services.AddAuthentication(opt =>
{
    opt.DefaultScheme = "Cookies";
    opt.DefaultChallengeScheme = "oidc";                
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", opt =>
{
    opt.SignInScheme = "Cookies";
    opt.Authority = discoverySettings.IdentityApi;
    opt.ClientId = "CRMClientMVC";
    opt.ResponseType = "code id_token";
    opt.SaveTokens = true;
    opt.ClientSecret = "MVCSecret";
    opt.GetClaimsFromUserInfoEndpoint = true;
    opt.Scope.Add("email");
    opt.Scope.Add("CRMApi");
});

和API:

builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", opt =>
{
    opt.RequireHttpsMetadata = false;
    opt.Authority = discoverySettings.IdentityApi;
    opt.Audience = "CRMApi";
});

我可以注册新用户并登录。当我转到任何子页面时,我都可以从 MVC 调用 API,这很棒。

问题

但是因为 MVC 和 API 之间的依赖关系很重要,我还必须从 API 调用 MVC。 这就是我遇到问题的地方。当我从 API 调用 MVC 时,我得到状态代码 200,但响应内容是 IS4 登录页面 html?!

<head>
    ...
    <title>IdentityServer4</title>    
    ...
</head>
...

这就是我在游戏机上看到的

MVC 控制台

info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
2023-03-14 11:16:08.9242|INFO|Microsoft.AspNetCore.Authorization.DefaultAuthorizationService|Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

IS 控制台

info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.AuthorizeEndpoint for /connect/authorize
info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
      Showing login: User is not authenticated

流程通常是这样的:

  1. 我在首页点击了一些东西

  2. 这会在 MVC 中使用 [Authorize] 属性执行一些操作

  3. MVC 调用 API

  4. 这会在具有 [Authorize] 属性的 API 中执行一些操作

  5. 但是 API 完成它的工作需要一些来自 MVC 的数据所以它调用 MVC

  6. 这会在 MVC 中执行另一个具有 [Authorize] 属性的操作 但这并不像描述的那样工作

这就是我从 API 进行调用的方式。我将 MVC 访问令牌复制到请求中

 var client = _httpClientFactory.CreateClient(httpClientType.ToString());
 
 var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
 var authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
 requestMessage.Headers.Authorization = authorization;

我试过什么

我从请求中删除了访问令牌,但结果是一样的。

我尝试添加 MVC 资源和范围,然后将其包含在 API 范围中,但这不起作用。可能是因为我调用 API->MVC 的方式。

 new ApiResource("CRMClient", "CRM Client MVC Resources")
{
    Scopes = { "CRMClient" },
    Enabled = true,
    UserClaims = { "sub", "name", "email" },
}
new ApiScope("CRMClient", "CRM Client MVC Scopes") 

在 API 客户端中我添加了这个范围

"CRMClient"

结果还是一样。

问题

我想知道我在这里错过了什么?我应该以某种方式在启动时授权我的 API 吗?将令牌存储在某处并在请求消息中将该令牌发送到 MVC?我在这里完全无能为力。 如果我添加第二个、第三个 API 并希望所有 API 和 MVC 能够相互通信怎么办?

我可以分享更多细节,例如如果需要的话。 提前谢谢你。

asp.net-core asp.net-core-mvc asp.net-core-webapi identityserver4
© www.soinside.com 2019 - 2024. All rights reserved.