前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core Swagger接入使用IdentityServer4 的 WebApi

ASP.NET Core Swagger接入使用IdentityServer4 的 WebApi

作者头像
乔达摩@嘿
发布2020-09-11 16:01:40
1.5K0
发布2020-09-11 16:01:40
举报
文章被收录于专栏:嘿dotNet嘿dotNet

写在前面

是这样的,我们现在接口使用了Ocelot做网关,Ocelot里面集成了基于IdentityServer4开发的授权中心用于对Api资源的保护。问题来了,我们的Api用了SwaggerUI做接口的自文档,那就蛋疼了,你接入了IdentityServer4的Api,用SwaggerUI调试、调用接口的话,妥妥的401,未授权啊。那有小伙伴就会说了,你SwaggerUI的Api不经过网关不就ok了?诶,好办法。但是:

  1. 我不想改变Url规则啊,我是/api开头的Url都是经过网关的,如果不经过网关要加端口或者改变Url规则,会给其他部门的同事带来麻烦(多个Url规则容易混淆);
  2. 另外是,因为生产环境是接入了IdentityServer4,我想测试环境从一开始就需要调用方熟悉接口的接入,避免平时用没有经过授权中心的Url调试,一到生产就出问题。

ok,废话讲得有点多,我们就直奔主题。

下面我们需要创建两个示例项目:

1、IdentityServer4的授权中心;

2、使用SwaggerUI做自文档的WebApi项目;

写得有点乱,本文源码地址: https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example

构建基于IdentityServer4授权中心

1、新建空白解决方案,并添加一个空的WebApi项目,IdentityServer

1557495509700
1557495509700

2、引用包。

代码语言:javascript
复制
Install-Package IdentityServer4

3、添加配置类:Config.cs

代码语言:javascript
复制
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace IdentityServer
{
    public static class Config
    {
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "alice",
                    Password = "alice"
                }
            };
        }

        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        }
        /// <summary>
        /// API信息
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiResource> GetApis()
        {
            return new[]
            {
                new ApiResource("swagger_api", "Demo SwaggerUI integrat Idp")
            };
        }
        /// <summary>
        /// 客服端信息
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "swagger_client",//客服端名称
                    ClientName = "Swagger UI client",//描述
                    AllowedGrantTypes = GrantTypes.Implicit,//Implicit 方式
                    AllowAccessTokensViaBrowser = true,//是否通过浏览器为此客户端传输访问令牌
                    RedirectUris =
                    {
                        "http://localhost:5001/swagger/oauth2-redirect.html"
                    },
                    AllowedScopes = { "swagger_api" }
                }
            };
        }
    }
}

4、修改Startup.cs

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace IdentityServer
{
    public class Startup
    {
        public IHostingEnvironment Environment { get; }

        public Startup(IHostingEnvironment environment)
        {
            Environment = environment;
        }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            var builder = services.AddIdentityServer()
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryApiResources(Config.GetApis())
                    .AddInMemoryClients(Config.GetClients())
                    .AddTestUsers(Config.GetUsers());

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                throw new Exception("need to configure key material");
            }
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();
            app.UseIdentityServer();
            app.UseMvcWithDefaultRoute();
        }
    }
}

ok,跑起来了

1557497033760
1557497033760

使用SwaggerUI做自文档的WebApi项目

1、添加WebApi项目,SwaggerUIApi

现在项目结构这样:

1557497204567
1557497204567

2、先添加SwaggerUI,先不接入IdentityServer

修改Startup.cs

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.Swagger;

namespace SwggerUIApi
{
    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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "ToDo API",
                    Description = "A simple example ASP.NET Core Web API",
                    TermsOfService = "None",
                    Contact = new Contact
                    {
                        Name = "Shayne Boyer",
                        Email = string.Empty,
                        Url = "https://twitter.com/spboyer"
                    },
                    License = new License
                    {
                        Name = "Use under LICX",
                        Url = "https://example.com/license"
                    }
                });
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), 
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });
            app.UseMvc();
        }
    }
}

得到这样的SwaggerUI:

1557497953754
1557497953754

我们调用一下接口:

杠杠的200:

1557497995457
1557497995457

3、接口项目我们接入IdentityServer4

修改:Startup.cs ,ConfigureServices方法,

代码语言:javascript
复制
  services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
  .AddIdentityServerAuthentication(options =>
           {
              options.Authority = "http://localhost:5000"; // IdentityServer服务器地址
              options.ApiName = "swagger_api"; // 用于针对进行身份验证的API资源的名称
              options.RequireHttpsMetadata = false; // 指定是否为HTTPS
          });

修改:Startup.cs ,Configure方法

代码语言:javascript
复制
app.UseAuthentication();

Ok,可以看到我们接口接入IdentityServer了。提示401,未授权;

1557498423814
1557498423814

3、接入IdentityServer

1、添加授权响应操作的过滤器,AuthResponsesOperationFilter.cs

代码语言:javascript
复制
using Microsoft.AspNetCore.Authorization;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SwggerUIApi
{
    public class AuthResponsesOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            //获取是否添加登录特性
            var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
             .Union(context.MethodInfo.GetCustomAttributes(true))
             .OfType<AuthorizeAttribute>().Any();

            if (authAttributes)
            {
                operation.Responses.Add("401", new Response { Description = "暂无访问权限" });
                operation.Responses.Add("403", new Response { Description = "禁止访问" });
                operation.Security = new List<IDictionary<string, IEnumerable<string>>>
                {
                    new Dictionary<string, IEnumerable<string>> {{"oauth2", new[] { "swagger_api" } }}
                };
            }
        }
    }
}

2、修改Startup.cs ,ConfigureServices方法的,services.AddSwaggerGen()

配置成这样:

代码语言:javascript
复制
     services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "ToDo API",
                    Description = "A simple example ASP.NET Core Web API",
                    TermsOfService = "None",
                    Contact = new Contact
                    {
                        Name = "Shayne Boyer",
                        Email = string.Empty,
                        Url = "https://twitter.com/spboyer"
                    },
                    License = new License
                    {
                        Name = "Use under LICX",
                        Url = "https://example.com/license"
                    }
                });
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);

                //接入identityserver
                c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Flow = "implicit", // 只需通过浏览器获取令牌(适用于swagger)
                    AuthorizationUrl = "http://localhost:5000/connect/authorize",//获取登录授权接口
                    Scopes = new Dictionary<string, string> {
                        { "swagger_api_scopde", "swagger_api access" }//指定客户端请求的api作用域。 如果为空,则客户端无法访问
                    }
                });
                c.OperationFilter<AuthResponsesOperationFilter>();
            });

3、我们还需给授权中心添加一个登陆界面

去: https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts/3_ImplicitFlowAuthentication/src/IdentityServer

下载这个两个文件夹,复制丢到IdentityServer项目下面:

1557500638819
1557500638819

项目结构:

1557500675473
1557500675473

4、我们运行看看

先启动Identityserver项目

运行SwaggerUI可以看到,这两个地方了个小锁头,表示已启用安全保护:

1557500788279
1557500788279

我们点一下上面的按钮:

1557500876183
1557500876183

哇,我们跳到了这里:

1557501003686
1557501003686

输入:alice/alice,点登录:

哇哇:

1557501070248
1557501070248

当然是Yes啦,然后这边变成这样了:

1557501113274
1557501113274

这是已获得授权状态,我们再次调用看看:

1557501152535
1557501152535

这里我们看到已经调用成功,仔细看请求,与前面简短的请求不同的是,现在请求里面带了access_token了,

这才是我们折腾这么久得来的宝贝。

总结

写得有点匆忙,希望大家能看得懂[捂脸];

源码地址:https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example

参考

https://github.com/domaindrivendev/Swashbuckle.AspNetCore

https://github.com/IdentityServer/IdentityServer4

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 构建基于IdentityServer4授权中心
    • 1、新建空白解决方案,并添加一个空的WebApi项目,IdentityServer
      • 2、引用包。
        • 3、添加配置类:Config.cs
          • 4、修改Startup.cs
          • 使用SwaggerUI做自文档的WebApi项目
            • 1、添加WebApi项目,SwaggerUIApi
              • 2、先添加SwaggerUI,先不接入IdentityServer
                • 3、接入IdentityServer
                  • 1、添加授权响应操作的过滤器,AuthResponsesOperationFilter.cs
                  • 2、修改Startup.cs ,ConfigureServices方法的,services.AddSwaggerGen()
                  • 3、我们还需给授权中心添加一个登陆界面
                  • 4、我们运行看看
              • 总结
              • 参考
              相关产品与服务
              多因子身份认证
              多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档