api - Identity Server 4 Postman 请求令牌不起作用
问题描述
我有一个 API,我正在使用 IdentityServer4 进行身份验证。所以,我有一个解决方案,其中包含我的 API 和 Identity Server 项目。到现在为止还挺好。我已经在没有身份验证的情况下测试了 API,它工作正常。现在我正在尝试使用 Postman 使用身份验证对其进行测试,但遇到了问题。我正在尝试使用授权代码授权类型请求令牌,并且我输入了所有需要的信息。我在控制台中不断遇到的错误是
09:51:31 信息] IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator 显示登录:用户未通过身份验证
我在网上查找了有关如何设置 API 和 Identity Server4 的教程,但他们都想创建一个客户端并显示一个登录屏幕。我不需要登录这个 API,而且我不知道我的客户会做什么。我想要的只是让客户端能够使用 clientID 和客户端 Secret 进行授权。然后获取他们可以用于其余 API 调用的访问令牌。我怎样才能做到这一点?下面是我的 API 和 IDP 的启动
API 启动
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddHttpContextAccessor();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5001";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
// adds an authorization policy to make sure the token is for scope 'api1'
services.AddAuthorization(options =>
{
options.AddPolicy("ApiScope", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "URCSAPI");
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
IDP 启动
public class Startup
{
public IWebHostEnvironment Environment { get; }
public Startup(IWebHostEnvironment environment)
{
Environment = environment;
}
public void ConfigureServices(IServiceCollection services)
{
var URCSIDPDataDBConnectionString =
"Server=localhost;Database=URCSIDP;Trusted_Connection=True;MultipleActiveResultSets=true";
// uncomment, if you want to add an MVC-based UI
services.AddControllersWithViews();
var builder = services.AddIdentityServer();
//.AddInMemoryIdentityResources(Config.Ids)
//.AddInMemoryApiResources(Config.Apis)
//.AddInMemoryClients(Config.Clients)
//.AddTestUsers(TestUsers.Users);
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
//builder.AddSigningCredential(LoadCertificateFromStore());
var migrationsAssembly = typeof(Startup)
.GetTypeInfo().Assembly.GetName().Name;
builder.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(URCSIDPDataDBConnectionString,
options => options.MigrationsAssembly(migrationsAssembly));
});
builder.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(URCSIDPDataDBConnectionString,
options => options.MigrationsAssembly(migrationsAssembly));
});
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//InitializeDatabase(app);
// uncomment if you want to add MVC
//app.UseStaticFiles();
//app.UseRouting();
app.UseIdentityServer();
// uncomment, if you want to add MVC
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapDefaultControllerRoute();
//});
}
public X509Certificate2 LoadCertificateFromStore()
{
string thumbPrint = "d4d681b3de4cd26fc030292aeea170e553810bdb";
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var certCollection = store.Certificates.Find(X509FindType.FindByThumbprint,
thumbPrint, true);
if (certCollection.Count == 0)
{
throw new Exception("The specified certificate wasn't found.");
}
return certCollection[0];
}
}
}
更新:添加我用来将信息添加到数据库的配置文件:
public static class Config
{
public static IEnumerable<IdentityResource> Ids =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Address()
};
public static IEnumerable<ApiResource> Apis =>
new ApiResource[]
{
new ApiResource(
"URCSAPI",
"Unit Rate ContractSystem API")
{
ApiSecrets = { new Secret("apisecret".Sha256()) }
}
};
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
AccessTokenType = AccessTokenType.Reference,
AccessTokenLifetime = 120,
AllowOfflineAccess = true,
UpdateAccessTokenClaimsOnRefresh = true,
ClientName = "Tesla",
ClientId = "Tesla",
AllowedGrantTypes = GrantTypes.ClientCredentials,
RequirePkce = false,
RedirectUris = new List<string>()
{
"https://localhost:6001/signin-oidc"
},
PostLogoutRedirectUris = new List<string>()
{
"https://localhost:6001/signout-callback-oidc"
},
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
"URCSAPI"
},
ClientSecrets =
{
new Secret("secret".Sha256())
}
}
};
}
解决方案
如果您试图保护未与交互式界面一起使用的 API(例如,用户在浏览器中的网站),那么验证代码流不是您想要使用的方法。Auth Code 流程是一个“交互式”流程,这意味着用户通过浏览器或移动应用程序在表单上登录。如果您的 API 是为机器对机器使用而设计的,或者其他人正在编写代码以直接访问您的 API,那么您应该使用客户端凭据流。此流程仅传递 clientId 和 clientSecret 以获取访问令牌以用于 API。
请参阅 ID4 网站上的此页面: https ://docs.identityserver.io/en/latest/quickstarts/1_client_credentials.html
查看您的 IdentityServer Config.cs 并确保其中的所有内容都是正确的。对于测试,使用 InMemory 存储(取消注释“AddInMemory”行)而不是 DB 中基于 EF 的存储更容易(您可以更快地进行调整,然后稍后移动到基于 DB 的存储)。
您将需要一个类型为“ClientCredentials”的客户端(请参阅上面 URL 中的“定义客户端”部分)。他们提供的基本示例如下所示:
public static IEnumerable<Client> Clients =>
new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
};
推荐阅读
- ios - 检测 iOS 表单关闭 Google 登录
- javascript - 合并两个表单值并发送
- rust - rust 如何决定使用哪个宏分支?
- html - 将数据保存在旧数组中的角度拖放
- sql - 在 sequelize 中创建一个数组并将数据存储为一个数组
- angular - 同源策略不允许在 iib 应用程序和角度读取远程资源
- r - 如何使用 fancyhead 在 rmarkdown 中包含自定义标题
- python - 如何抑制指数显示输出
- pandas - Pandas ETL:如何轻松管理两个大表的列映射?
- mysql - 无法使用 MySQL ODBC 3.51.30 驱动程序创建新的文件数据源以连接到 MySQL,但使用连接器 v8.0.23 有效