ASP.Net Core Web Api 使用 IdentityServer4 最新版 踩坑记录
辅助工具
日志追踪包 : 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");
}
}
此处有两个验证:
- POST请求 √
- 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,验证结果即为最终结果
把IdentityResource的Name值配置到Client中的AllowedScopes去,然后再在传参里使用IdentityResource的Name值
<调用结果>
{
"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... 总算通了
总结
- 传参需要使用 application/x-www-form-urlencoded
- 配置Client的AllowedScopes值时要使用IdentityResource的Name值,或者配置ApiScope
- 传参传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 最新版 踩坑记录的更多相关文章
- .net core 微服务架构-docker的部署-包括网关服务(Ocelot)+认证服务(IdentityServer4)+应用服务(asp.net core web api)
本文主要介绍通过Docker来部署通过.Net Core开发的微服务架构,部署的微服务主要包括统一网关(使用Ocelot开发).统一认证(IdentityServer4).应用服务(asp.net c ...
- 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)
对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...
- 在ASP.NET Core Web API上使用Swagger提供API文档
我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...
- Docker容器环境下ASP.NET Core Web API应用程序的调试
本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...
- 在docker中运行ASP.NET Core Web API应用程序
本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Cor ...
- ASP.NET Core Web API Cassandra CRUD 操作
在本文中,我们将创建一个简单的 Web API 来实现对一个 “todo” 列表的 CRUD 操作,使用 Apache Cassandra 来存储数据,在这里不会创建 UI ,Web API 的测试将 ...
- 在Mac下创建ASP.NET Core Web API
在Mac下创建ASP.NET Core Web API 这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢? 原因如下: 官方文档涉 ...
- ASP.NET Core Web API 开发-RESTful API实现
ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...
- Docker容器环境下ASP.NET Core Web API
Docker容器环境下ASP.NET Core Web API应用程序的调试 本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Dock ...
随机推荐
- C语言:总结
1除法运算:两整数相除,结果为整数: 任意浮点数参与的除法运算结果为浮点型.所以pow(16,1/2)=1 pow(16,1.0/2)=4.00 pow(64,1.0/3)=4.00 球的体积v ...
- vue3 封装简单的 tabs 切换组件
背景:公司项目要求全部换成 vue3 ,而且也没有应用像 element-ui 一类的UI组件,用到的公共组件都是根据项目需求封装的,下面是使用vue3实现简单的tabs组件,我只是把代码分享出来,实 ...
- Java基础00-内部类23
1. 内部类 内部类 1.1 内部类概述 代码示例: 1.2 成员内部类 代码示例: 创建一个成员内部类:定义时没有小括号是因为类是没有形参的.在类的成员位置,就是成员内部类了 创建测试类:这里发现不 ...
- ls仅列出当前目录下的所有目录
ls -d */ -d仅列出目录本身,而不列出其中的内容 *通配符,所有的字符 /目录的标识
- MySQL -- 表联结
创建联结:(使用WHERE联结)SELECTvend_name,prod_name,prod_priceFROMvendors,productsWHEREvendors.vend_id=product ...
- uiautomator2 入门教程
一.前言 在 Android 自动化测试方面,Google 提供了一个基于 Java 开发的库 UiAutomator,基本上支持所有的 Android 事件操作,使用简单. 在此基础上,有大佬开发出 ...
- MySQL检查与性能优化示例脚本
最近在玩python,为了熟悉一下python,写了个mysql的检查与性能优化建议的脚本. 虽然,真的只能算是一个半成残次品.也拿出来现眼一下. 不过对于初学者来说,还是有一定的参考价值的.比如说如 ...
- linux删除命令
Linux下的命令,删除文件夹下的所有文件,而不删除文件夹本身rm -rf *
- Python入门 -- 001
在Windows系统下安装python: 从Python的官方网站(http://www.python.org/)下载最新版的程序安装包. 安装完成后设置路径,使得在Windows系统的CMD中能够通 ...
- Springboot通过过滤器实现对请求头的修改
之前在一个项目中有一个API服务需要重构,尤其是接口的用户身份校验,原先的实现是将用户token放在URL请求参数中,然后通过AOP进行校验,现在要统一将token放在header中,但是这样修改会让 ...