辅助工具

日志追踪包 : Serilog.AspNetCore

源码查看工具 : ILSpy

项目环境 ###:

ASP.NetCore 3.1

IdentityServer4 4.0.0+

主题内容

测试登录方式 : password

错误内容:

connect/token 登陆出错

但百度/google网上的示例没有找到正确的调用方式,无奈只能自己动手,丰衣足食...

首先,先按照之前版本进行传参

  • POST请求
  • url: connect/token
  • 参数传递通过 form-data

调用结果:

<调用结果>
HTTP : 400 {
"error": "invalid_request"
}

查找调用日志

Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token

可以看到地址匹配是成功的,那就是校验不通过了,接着看一下这个类的源码,找到错误触发地

public async Task<IEndpointResult> ProcessAsync(HttpContext context)
{
if (!HttpMethods.IsPost(context.Request.Method) || !context.Request.HasApplicationFormContentType())
{
return Error("invalid_request");
}
}

此处有两个验证:

  1. POST请求 √
  2. HasApplicationFormContentType ?

查看方法定义:

internal static bool HasApplicationFormContentType(this HttpRequest request)
{
if (request.ContentType == null)
{
return false;
}
if (MediaTypeHeaderValue.TryParse(request.ContentType, out MediaTypeHeaderValue parsedValue))
{
return parsedValue.MediaType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase);
}
return false;
}

... 好样的,最新版改用了application/x-www-form-urlencoded传参

然后改一下传参方式接着调用:

<调用结果>
HTTP : 400 {
"error": "invalid_scope"
}

换了个错误,至少说明传参改动还是有效的...

查找操作日志:

IdentityServer4.Validation.TokenRequestValidator
No scopes found in request

key code:

string text = parameters.Get("scope");

if (text.IsMissing())
{
text = clientAllowedScopes.Distinct().ToSpaceSeparatedString();
}
List<string> requestedScopes = text.ParseScopesString();
if (requestedScopes == null)
{
LogError("No scopes found in request");
return false;
}

scope取值:

如果没有传值,就去client中取

public static List<string> ParseScopesString(this string scopes)
{
if (scopes.IsMissing())
{
return null;
}
scopes = scopes.Trim();
List<string> list = scopes.Split(new char[1]
{
' '
}, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList();
if (list.Any())
{
list.Sort();
return list;
}
return null;
}

如果有传值 就用传值的获取,多个scope用' '分隔

在配置中,是有AllowedScopes配置,但取不出来? 先不管,用传值方式先试试...

<调用结果>
HTTP : 400 {
"error": "invalid_scope"
}

??? 再查下日志:

IdentityServer4.Validation.DefaultResourceValidator

Scope api1 not found in store.

还好错误变了,不然没得玩了...

先确认配置信息:

return new List<ApiResource>
{
new ApiResource("api1", "My API")
};

是有这个api1的,好吧,只能再去查看源码了

DefaultResourceValidator Scope验证分析

IdentityResource identity = resourcesFromStore.FindIdentityResourcesByScope(requestedScope.ParsedName);
if (identity != null)
{
if (await IsClientAllowedIdentityResourceAsync(client, identity))
{
result.ParsedScopes.Add(requestedScope);
result.Resources.IdentityResources.Add(identity);
}
else
{
result.InvalidScopes.Add(requestedScope.RawValue);
}
return;
}

首先先通过name去拿IdentityResource,拿到了IdentityResource验证结果即为最终结果

ApiScope apiScope = resourcesFromStore.FindApiScope(requestedScope.ParsedName);

没有拿到IdentityResource则再通过name去拿ApiScope,验证结果即为最终结果

IdentityResourceName值配置到Client中的AllowedScopes去,然后再在传参里使用IdentityResourceName

<调用结果>
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjUyM0EzMjE0Q0M4MzAzQjJBRDA2Mzk5N0E2RDI1NDEyIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTQxMTAwNjcsImV4cCI6MTU5NDExMzY2NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiY2xpZW50X2lkIjoicm8uY2xpZW50Iiwic3ViIjoiMiIsImF1dGhfdGltZSI6MTU5NDExMDA2NywiaWRwIjoibG9jYWwiLCJqdGkiOiJCMEY1NEI2NDI1QzUwRDU2REVEMjBGQUY0QkMwNTE5MiIsImlhdCI6MTU5NDExMDA2Nywic2NvcGUiOlsib3BlbmlkIl0sImFtciI6WyJwd2QiXX0.PqYMwqHfZ3CHtE8q_eCi5H1FVCPKe01uSPiSTNjV0q1m61s98OQezo9M3FCc4bGTw4c6VruylSQAbtT6sid2nYXV05Eq_fD_4KKPTya6NLuTdwgdUohzNN10f3SC0ea1nDhv_94Ewkov_9OWrCSLxAX9yVFKDDs6dB3V53_49n4-3Hd9BkCOevWk-_FzpkMOOhYMi-5LNeZRAXH3G5_GZ7INtypCUx2f0_v84UzQxx2LjcovzAy0ZR3GgFvAh5rgRwd5oBVeiLZOt2ZjvV0b5NAtPSbiEcufFK5box6qm_q2M6GrrMBUm0aTTTd3Vu6Zx-pjjITHQN934EICRKWYFg",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "openid"
}

over... 总算通了


总结

  1. 传参需要使用 application/x-www-form-urlencoded
  2. 配置ClientAllowedScopes值时要使用IdentityResourceName值,或者配置ApiScope
  3. 传参传scope时,通过制指定scope进行验证,未传时通过配置的信息(AllowedScopes)进行验证

新版的ApiResource作用

待补充...

配置参考

public static class Config
{
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password"
},
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password"
}
};
} public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId()
};
} public static IEnumerable<Client> GetClients()
{
return 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" }
},
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "openid" }
}
};
}
} public void ConfigureServices(IServiceCollection services)
{ var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers()); builder.AddDeveloperSigningCredential(); } // 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.UseIdentityServer(); }

ASP.Net Core Web Api 使用 IdentityServer4 最新版 踩坑记录的更多相关文章

  1. .net core 微服务架构-docker的部署-包括网关服务(Ocelot)+认证服务(IdentityServer4)+应用服务(asp.net core web api)

    本文主要介绍通过Docker来部署通过.Net Core开发的微服务架构,部署的微服务主要包括统一网关(使用Ocelot开发).统一认证(IdentityServer4).应用服务(asp.net c ...

  2. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  3. 在ASP.NET Core Web API上使用Swagger提供API文档

    我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...

  4. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

  5. 在docker中运行ASP.NET Core Web API应用程序

    本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Cor ...

  6. ASP.NET Core Web API Cassandra CRUD 操作

    在本文中,我们将创建一个简单的 Web API 来实现对一个 “todo” 列表的 CRUD 操作,使用 Apache Cassandra 来存储数据,在这里不会创建 UI ,Web API 的测试将 ...

  7. 在Mac下创建ASP.NET Core Web API

    在Mac下创建ASP.NET Core Web API 这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢? 原因如下: 官方文档涉 ...

  8. ASP.NET Core Web API 开发-RESTful API实现

    ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...

  9. Docker容器环境下ASP.NET Core Web API

    Docker容器环境下ASP.NET Core Web API应用程序的调试 本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Dock ...

随机推荐

  1. python使用笔记18--写日志

    1 import nnlog 2 import traceback 3 #level:输出日志级别,debug:把所有的日志都打印出来,info:打印info以上的日志, 4 # warning:打印 ...

  2. python使用笔记009--小练习

    1.密码生成器 1 ''' 2 1.写一个生产密码的程序,输入几,就产生几条密码,密码产生的不重复. 3 要求密码:长度6-12,密码必须包含 大写字母.小写字母.数字 4 产生完密码后存到一个文件里 ...

  3. PYTHON UNRAR

    下载安装VINRAR 安装上面的下载文件 安装位置:32位具体位置 C:\Program Files (x86)\UnrarDLL      64位具体位置:C:\Program Files (x86 ...

  4. vue-qiankun公司微前端项稳定目落地后的总结(附github仓库demo,将会持续更新)

    ️本文为博客园社区首发文章,未获授权禁止转载 大家好,我是aehyok,一个住在深圳城市的佛系码农‍♀️,如果你喜欢我的文章,可以通过点赞帮我聚集灵力️. 个人github仓库地址: https:gi ...

  5. Java基础00-形参和返回值22

    1. 形参和返回值 1.1 类名作为形参和返回值 1.2 抽象类名作为形参和返回值 代码示例: 方法的形参是抽象类名 抽象动物类:定义了一个抽象的eat方法 动物的操作类:创建一个useAnimal方 ...

  6. EasyUI:combotree(树形下拉框)复选框选中父节点(子节点的状态也全部选中)输入框中只显示父节点的文本值

    参考: https://blog.csdn.net/weixin_43236850/article/details/100320564

  7. Pytest单元测试框架之setup/teardown模块示例操作

    """模块级(setup_module/teardown_module)开始于模块始末,全局的函数级(setup_function/teardown_function)只 ...

  8. kubernetes/k8s CSI分析-容器存储接口分析

    更多 k8s CSI 的分析,可以查看这篇博客kubernetes ceph-csi分析,以 ceph-csi 为例,做了详细的源码分析. 概述 kubernetes的设计初衷是支持可插拔架构,从而利 ...

  9. Python - 基础数据类型 list 列表

    什么是列表 列表是一个有序的序列 列表中所有的元素放在 [ ] 中间,并用逗号分开 一个 列表 可以包含不同类型的元素,但通常使用时各个元素类型相同 特征 占用空间小,浪费内存空间少 声明列表变量 列 ...

  10. 第四篇--Beyond Compare4 试用期30天后

    30天后删除BCUnrar.dll这个文件,继续使用30天.还有就是注册表中regedit-->HEKY_CURRENT_USER-->Software-->Scooter Soft ...