如何使用 Postman 调用 Identity Server 4 进行登录

Posted

技术标签:

【中文标题】如何使用 Postman 调用 Identity Server 4 进行登录【英文标题】:How to call Identity Server 4 with Postman for login 【发布时间】:2020-01-31 11:37:38 【问题描述】:

我在 Visual Studio 'TourManagement' 中有一个解决方案,其中包含 2 个 .Net 核心项目。一个是使用 Identity Server 4 的 IDP,第二个项目是 IDP 项目保护的 TourManagement 的 RESTful API。我的问题是如何使用 Postman 调用 Identity Server 4 来获取令牌并通过在邮递员身份服务器返回的标头中传递这些令牌来调用 TourManagement Bands API?我的代码如下。

IDP 项目中的启动类

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 项目中的配置类

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();
        
    

Tourmanagement 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);
        
    


【问题讨论】:

您可以通过在浏览器中键入来查看身份服务器端点:localhost:5000/.well-known/openid-configuration(localhost:5000 是我的应用使用您的地址) 【参考方案1】:

关键是使用 Postman 中的隐式流来获取访问令牌以访问 tourmanagementapi 进行测试。

首先在GetClients函数的客户端配置中将AllowAccessTokensViaBrowser设置为true,这样就可以通过浏览器通道传输访问令牌了:

new Client

.....
    AllowAccessTokensViaBrowser =true,
.....

在邮递员方面,请执行以下操作:

    输入您的 api 的 URL。

    Authorization类型中,有一个下拉列表,选择OAuth2

    选择它后,您会看到一个显示获取访问令牌的按钮,单击它并输入以下信息(根据您的代码):

    不要输入 openid/profile 作为 Scope,因为您在 Postman 中使用 Oauth2。

    点击Request Token,你会看到添加了一个名为TokenName的新令牌 最后,确保将令牌添加到标题中,然后单击Use Token。发送请求作为授权标头时,令牌将可用:

【讨论】:

非常感谢您的详细帮助。它的工作。【参考方案2】:

我写了一个关于如何做到这一点的完整的分步教程,因为这个主题的答案对我来说不够好。

与其他响应不同的是,如何自动获取和存储不记名令牌并将其用于测试而无需执行任何其他操作。非常适合集成测试您的控制器类。

https://medium.com/@rotter.axel/automatically-sign-in-to-identity-server-4-with-postman-and-test-net-core-controller-methods-bc5d8feb199e

【讨论】:

以上是关于如何使用 Postman 调用 Identity Server 4 进行登录的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Blazor 组件调用“/Identity/Account/ExternalLogin”?

如何在 Springboot 应用程序中捕获通过 POSTMAN 发送的 JSONObject?

如何使用 Postman 客户端调用 Twitter API

如何在 IdentityServer ASP.NET Core 中使用 Postman 使用 AntiForgeryToken 调用 API

如何从 POSTMAN 调用 WCF 服务方法

如何使用 Oauth2 和 chrome.identity 获取 Facebook 令牌