我在Visual Studio 'TourManagement'中有一个解决方案,其中包含两个.NET Core项目。一个是使用Identity Server 4的IDP,第二个项目是由IDP项目保护的TourManagement RESTful API。我的问题是如何使用Postman调用Identity Server 4以获取令牌,并通过在Postman中从身份验证服务器返回的标头传递这些令牌来调用TourManagement Bands API?我的代码如下。
IDP项目中的Startup类
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Marvin.IDP
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.GetUsers())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryClients(Config.GetClients());
services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(c => c.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
}
IDP项目中的Config类。
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;
namespace Marvin.IDP
{
public static class Config
{
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "fec0a4d6-5830-4eb8-8024-272bd5d6d2bb",
Username = "Jon",
Password = "jon123",
Claims = new List<Claim>
{
new Claim("given_name", "Jon"),
new Claim("family_name", "Doe"),
new Claim("role", "Administrator"),
}
},
new TestUser
{
SubjectId = "c3b7f625-c07f-4d7d-9be1-ddff8ff93b4d",
Username = "Steve",
Password = "steve123",
Claims = new List<Claim>
{
new Claim("given_name", "Steve"),
new Claim("family_name", "Smith"),
new Claim("role", "Tour Manager"),
}
}
};
}
public static List<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", "Your role(s)", new []{"role"}),
};
}
internal static IEnumerable<ApiResource> GetApiResources()
{
return new[] {
new ApiResource("tourmanagementapi", "Tour Management API", new[] { "role" })
};
}
public static List<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientName = "Tour Management",
ClientId="tourmanagementclient",
AllowedGrantTypes = GrantTypes.Implicit,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
RedirectUris =new List<string>
{
"https://localhost:4200/signin-oidc",
"https://localhost:4200/redirect-silentrenew"
},
AccessTokenLifetime = 180,
PostLogoutRedirectUris = new[]{
"https://localhost:4200/" },
AllowedScopes = new []
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"tourmanagementapi",
}
}
};
}
}
}
TourManagement API 项目中的启动类
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Linq;
using TourManagement.API.Authorization;
using TourManagement.API.Services;
namespace TourManagement.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization();
services.AddScoped<IAuthorizationHandler, UserMustBeTourManagerRequirementHandler>();
services.AddMvc(setupAction =>
{
setupAction.ReturnHttpNotAcceptable = true;
})
.AddJsonOptions(options =>
{
options.SerializerSettings.DateParseHandling = DateParseHandling.DateTimeOffset;
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
});
services.AddCors(options =>
{
options.AddPolicy("AllowAllOriginsHeadersAndMethods",
builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
var connectionString = Configuration["ConnectionStrings:TourManagementDB"];
services.AddDbContext<TourManagementContext>(o => o.UseSqlServer(connectionString));
services.AddScoped<ITourManagementRepository, TourManagementRepository>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IUserInfoService, UserInfoService>();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44398";
options.ApiName = "tourmanagementapi";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(appBuilder =>
{
appBuilder.Run(async context =>
{
context.Response.StatusCode = 500;
await context.Response.WriteAsync("An unexpected fault happened. Try again later.");
});
});
}
app.UseCors("AllowAllOriginsHeadersAndMethods");
app.UseAuthentication();
app.UseMvc();
}
}
}
巡演管理 API 项目中的乐队控制器
using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using TourManagement.API.Dtos;
using TourManagement.API.Services;
namespace TourManagement.API.Controllers
{
[Route("api/bands")]
[Authorize]
public class BandsController : Controller
{
private readonly ITourManagementRepository _tourManagementRepository;
public BandsController(ITourManagementRepository tourManagementRepository)
{
_tourManagementRepository = tourManagementRepository;
}
[HttpGet]
public async Task<IActionResult> GetBands()
{
var bandsFromRepo = await _tourManagementRepository.GetBands();
var bands = Mapper.Map<IEnumerable<Band>>(bandsFromRepo);
return Ok(bands);
}
}
}