辅助工具

日志追踪包 : 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. Django基础005-Django开发的整体过程

    1.写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:id ...

  2. 前端-Vue基础2

    1.过滤器 前台通过后台传值,要对后台传过来的变量进行特殊处理,比如根据id转成中文等: 1.1 局部过滤器 局部过滤器只针对一个Vue实例 默认将|左侧count传递给右侧方法 {{count|fi ...

  3. SQL USE语句(选择数据库)

    对于大型的软件系统,会存在多个数据库,用来存储不同的数据,那么我们在开始操作之前,需要选择一个需要操作的数据库,进行后续数据的增.删.改.查工作. SQL USE语句用于选择SQL模式中的任何现有数据 ...

  4. Leetcode13. 罗马数字转整数Leetcode14. 最长公共前缀Leetcode15. 三数之和Leetcode16. 最接近的三数之和Leetcode17. 电话号码的字母组合

    > 简洁易懂讲清原理,讲不清你来打我~ 输入字符串,输出对应整数 ![在这里插入图片描述](https://img-blog.csdnimg.cn/63802fda72be45eba98d9e4 ...

  5. 超详细!Vuex手把手教程

    目录 1,前言 2,Vuex 是什么 3,5大属性说明 4,state 4.1 直接访问 4.1 使用mapState映射 5,getters 5.1 先在vuex中定义getters 5.2 直接获 ...

  6. SQlL 中 where 1=1

    提升某种执行效率? 其实,1=1 是永恒成立的,意思无条件的,也就是说在SQL语句中有没有这个1=1都可以. 这个1=1常用于应用程序根据用户选择项的不同拼凑where条件时用的. 如:web界面查询 ...

  7. 一台电脑安装两个不同版本的MySQL

    背景: 本人电脑上已有mysql-8.0.12-winx64,并且可以使用.但由于工作需要,得使用mysql-5.5.59-winx64,已有mysql-5.5.59-winx64的解压好的安装包 参 ...

  8. 第五篇--Chorme浏览器主页被篡改

    解决方法:关闭谷歌浏览器,右击桌面快捷方式,查看属性,然后将target后面的网址删掉.并且任务栏的google打开方式,最好也把流氓网址删掉.之后就正常了.

  9. python2 与 python3 依赖包冲突问题

    原文链接   https://www.2cto.com/database/201805/749294.html 执行pip的时候取的是/usr/bin这里的pip,查看这里是否存在pip3,没有的话需 ...

  10. 一文带你搞定AOP切面

    摘要:AOP在spring中又叫"面向切面编程",是对传统我们面向对象编程的一个补充,主要操作对象就是"切面",可以简单的理解它是贯穿于方法之中,在方法执行前. ...