在准备好 eShopOnContainer 环境,运行起来之后,不幸的是,我遇到了不能登录的错误。

从错误信息中,可以看到 unauthorized_client 的内容。这是为什么呢?

从 eShopOnContainers 的 Wiki 上,可以看到找到这篇文章:unauthorized_client error on Login

这里面介绍了导致该问题的几个原因。

其中的一个是不能使用 localhost 作为主机名来访问 eShop 站点,因为 eShop 在 Identity 服务器上注册的客户端使用了 docker 中的名称 host.docker.internal

那么,注册和访问的信息来自哪里呢?

在访问的时候,使用了来自 src/.env 文件中配置的环境变量信息, docker-compose 将会自动使用该文件来获得环境变量的配置信息。见 Environment variables in Compose

You can set default values for environment variables using a .env file,

which Compose automatically looks for in project directory (parent folder of your Compose file).

Values set in the shell environment override those set in the .env file.

该文件开始部分内容如下:

# Compose supports declaring default environment variables in an environment file named .env placed in the folder docker-compose command is executed from (current working directory).
# Compose expects each line in an env file to be in VAR=VAL format. Lines beginning with # (i.e. comments) are ignored, as are blank lines.
# Note: Values present in the environment at runtime will always override those defined inside the .env file. Similarly, values passed via command-line arguments take precedence as well. # The IP below should be swapped to your real IP or DNS name, like 192.168.88.248, etc. if testing from remote browsers or mobile devices # Use this values to run the app locally in Windows
ESHOP_EXTERNAL_DNS_NAME_OR_IP=host.docker.internal
ESHOP_STORAGE_CATALOG_URL=http://host.docker.internal:5202/c/api/v1/catalog/items/[0]/pic/ # Use this values to run the app locally in Mac
# ESHOP_EXTERNAL_DNS_NAME_OR_IP=docker.for.mac.localhost
# ESHOP_STORAGE_CATALOG_URL=http://docker.for.mac.localhost:5202/c/api/v1/catalog/items/[0]/pic/ # Use this values to run the app locally in Linux
# ESHOP_EXTERNAL_DNS_NAME_OR_IP=docker.for.linux.localhost
# ESHOP_STORAGE_CATALOG_URL=http://docker.for.linux.localhost:5202/c/api/v1/catalog/items/[0]/pic/

可以看到在 Windows 环境下,访问地址将会使用 host.docker.internal,而在 mac OS 下,则应该使用 docker.for.mac.localhost

在 eShop MVC 项目的配置文件 eShopOnContainers/src/Web/WebMVC/appsettings.json 中,可以看到使用的默认地址

{
"CatalogUrl": "http://localhost:5101",
"OrderingUrl": "http://localhost:5102",
"BasketUrl": "http://localhost:5103",
"IdentityUrl": "http://localhost:5105",
"CallBackUrl": "http://localhost:5100/",

在 .NET 中,它们可以被环境变量所覆盖。在 docker-compose 所使用的 docker-compose.override.yml 文件,它们被容器定义的环境变量所覆盖。

  webmvc:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- PurchaseUrl=http://webshoppingapigw
- IdentityUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
- SignalrHubUrl=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5202
- IdentityUrlHC=http://identity-api/hc
- UseCustomizationData=True
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
- UseLoadTest=${USE_LOADTEST:-False}
ports:
- "5100:80"

在 Identity 中定义的时候,

eShopOnContainers/src/Services/Identity/Identity.API/Configuration/Config.cs 中,预先定义来客户端的配置信息。以 MVC 项目为例:

new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
ClientSecrets = new List<Secret>
{ new Secret("secret".Sha256())
},
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client
AllowedGrantTypes = GrantTypes.Hybrid,
AllowAccessTokensViaBrowser = false,
RequireConsent = false,
AllowOfflineAccess = true,
AlwaysIncludeUserClaimsInIdToken = true,
RedirectUris = new List<string>
{
$"{clientsUrl["Mvc"]}/signin-oidc"
},
PostLogoutRedirectUris = new List<string>
{
$"{clientsUrl["Mvc"]}/signout-callback-oidc"
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket",
"webshoppingagg",
"orders.signalrhub",
"webhooks"
},
AccessTokenLifetime = 60*60*2, // 2 hours
IdentityTokenLifetime= 60*60*2 // 2 hours
},

这个 clientsUrl 来自 src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs 中,这些信息来自配置文件。

public async Task SeedAsync(ConfigurationDbContext context, IConfiguration configuration)
{ //callbacks urls from config:
var clientUrls = new Dictionary<string, string>(); clientUrls.Add("Mvc", configuration.GetValue<string>("MvcClient"));
clientUrls.Add("Spa", configuration.GetValue<string>("SpaClient"));
clientUrls.Add("Xamarin", configuration.GetValue<string>("XamarinCallback"));
clientUrls.Add("BasketApi", configuration.GetValue<string>("BasketApiClient"));
clientUrls.Add("OrderingApi", configuration.GetValue<string>("OrderingApiClient"));
clientUrls.Add("MobileShoppingAgg", configuration.GetValue<string>("MobileShoppingAggClient"));
clientUrls.Add("WebShoppingAgg", configuration.GetValue<string>("WebShoppingAggClient"));
clientUrls.Add("WebhooksApi", configuration.GetValue<string>("WebhooksApiClient"));
clientUrls.Add("WebhooksWeb", configuration.GetValue<string>("WebhooksWebClient"));

而它们又会被 docker-compose 所配置的环境变量所覆盖掉。见 docker-compose.override.yml 文件中,针对 Identity-API 的配置:

  identity-api:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=http://0.0.0.0:80
- SpaClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5104
- XamarinCallback=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105/xamarincallback
- ConnectionString=${ESHOP_AZURE_IDENTITY_DB:-Server=sqldata;Database=Microsoft.eShopOnContainers.Service.IdentityDb;User Id=sa;Password=Pass@word}
- MvcClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5100
- BasketApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5103
- OrderingApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5102
- MobileShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5120
- WebShoppingAggClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5121
- WebhooksApiClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5113
- WebhooksWebClient=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5114
- UseCustomizationData=True
- ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY}
- OrchestratorType=${ORCHESTRATOR_TYPE}
ports:
- "5105:80"

所以,一定要使用正确的地址访问网站,才能成功登录,直接使用 localhost 虽然可以看到首页,在登录的时候,却会因为地址的问题而出现错误。

如果注册的地址出现问题,能不能修改一下呢?这些注册信息最终会保存到数据库中,在需要的情况下,直接修改数据库中的信息也是可以的。

甚至并不需要你安装特别的工具,在 SQLServer 的镜像中,已经提供了 sqlcmd 这个命令行工具。可以使用它来完成修改工作。

首先,我们可以连接到运行的容器中,然后使用 sqlcmd 登录到运行在此容器中的数据库,最后,就可以执行 SQL 命令了。

  • 连接到容器的时候,指定运行的 bash
  • 示例中 SQLServer 数据库的默认登录帐号是 sa/Pass@word,它可以在 docker-compose 定义中找到。
  • 在 sqlcmd 中,输入一条 sql 命令之后,需要使用 go 来执行。
docker exec -it src_sqldata_1 "bash"

/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Pass@word 

use [Microsoft.eShopOnContainers.Service.IdentityDb]
go 1> select id, left(redirectUri, 100), Clientid from dbo.ClientRedirectUris
2> go
id Clientid
----------- ---------------------------------------------------------------------------------------------------- -----------
1 http://host.docker.internal:5104/ 1
2 http://10.121.122.162:5105/xamarincallback 2
3 http://host.docker.internal:5100/signin-oidc 3
4 http://host.docker.internal:5114/signin-oidc 4
5 http://host.docker.internal:5100/signin-oidc 5
6 http://host.docker.internal:5103/swagger/oauth2-redirect.html 6
7 http://host.docker.internal:5102/swagger/oauth2-redirect.html 7
8 http://host.docker.internal:5120/swagger/oauth2-redirect.html 8
9 http://host.docker.internal:5121/swagger/oauth2-redirect.html 9
10 http://host.docker.internal:5113/swagger/oauth2-redirect.html 10
(10 rows affected) insert dbo.ClientRedirectUris ( redirectUri, ClientId) values ( 'http://docker.for.mac.localhost:5104/', 1)
(1 rows affected) 1> select id, left(redirectUri, 100), Clientid from dbo.ClientRedirectUris
2> go
id Clientid
----------- ---------------------------------------------------------------------------------------------------- -----------
1 http://host.docker.internal:5104/ 1
2 http://10.121.122.162:5105/xamarincallback 2
3 http://host.docker.internal:5100/signin-oidc 3
4 http://host.docker.internal:5114/signin-oidc 4
5 http://host.docker.internal:5100/signin-oidc 5
6 http://host.docker.internal:5103/swagger/oauth2-redirect.html 6
7 http://host.docker.internal:5102/swagger/oauth2-redirect.html 7
8 http://host.docker.internal:5120/swagger/oauth2-redirect.html 8
9 http://host.docker.internal:5121/swagger/oauth2-redirect.html 9
10 http://host.docker.internal:5113/swagger/oauth2-redirect.html 10
1002 http://docker.for.mac.localhost:5104/ 1 (11 rows affected) > insert dbo.ClientRedirectUris ( redirectUri, ClientId) values ( 'http://docker.for.mac.localhost:5100/signin-oidc', 3)
> go
(1 rows affected) 1> select id, left(redirectUri, 100), Clientid from dbo.ClientRedirectUris
2> go
id Clientid
----------- ---------------------------------------------------------------------------------------------------- -----------
1 http://host.docker.internal:5104/ 1
2 http://10.121.122.162:5105/xamarincallback 2
3 http://host.docker.internal:5100/signin-oidc 3
4 http://host.docker.internal:5114/signin-oidc 4
5 http://host.docker.internal:5100/signin-oidc 5
6 http://host.docker.internal:5103/swagger/oauth2-redirect.html 6
7 http://host.docker.internal:5102/swagger/oauth2-redirect.html 7
8 http://host.docker.internal:5120/swagger/oauth2-redirect.html 8
9 http://host.docker.internal:5121/swagger/oauth2-redirect.html 9
10 http://host.docker.internal:5113/swagger/oauth2-redirect.html 10
1002 http://docker.for.mac.localhost:5104/ 1
1003 http://docker.for.mac.localhost:5100/signin-oidc 3 (12 rows affected)

https://github.com/dotnet-architecture/eShopOnContainers/wiki/unauthorized_client-error-on-login

eShopOnContainer 中 unauthorized_client error 登录错误处理的更多相关文章

  1. MinGW-w64安装过程中出现ERROR res错误的问题

    使用 mingw-get-setup.exe 安装.在官网http://www.mingw.org/上搜索download/installer,点击下载. 如果使用 mingw-w64-install ...

  2. 孙鑫视频学习:改变窗口过程函数中出现error C2440错误的解决方法

    在Visual Studio 2010中,即使代码是完完全全按照孙鑫视频中的敲,也会在出现error C2440,这是因为开发平台由VC6.0升级至VS2010,需要将原有的项目迁移.VS2010对消 ...

  3. Socket程序中的Error#10054错误

    近期使用winSock做的一个网络项目中,使用TCP+Socket连接编写的一个多线程的网络程序,功能是client负责不断地向server端发送数据,服务端负责接收数据.client是一个DLL,服 ...

  4. VS2010中fatal error LNK1123错误的解决方案

    问题描述: 在VS2010项目编译时会出现如下错误:LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 解决方案: 查找是否有两个cvtres.exe ...

  5. MySQL创建函数报“ERROR 1418 ”错误,不能创建函数

    MySQL创建函数报ERROR 1418错误,不能创建函数,根据官方提示是说,不能创建函数可能是一个安全设置方面的配置或功能未开启原因,下面我们一起来看.   错误 ERROR 1418 (HY000 ...

  6. Linux中syntax error near unexpected token 错误提示解决方法

    Linux中syntax error near unexpected token ... 错误提示有一般有两种原因: 1)window和Linux下换行符不一致导致 window下的换行和Linux下 ...

  7. MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause

    MySQL中执行sql语句错误 Error Code: 1093. You can't specify target table 'car' for update in FROM clause 201 ...

  8. ArcGISEngine中GP工具奇怪错误问题error(s) have been detected for layer

    运行时环境:使用CADToGeodatabase工具执行DWG文件转gdb过程,多次执行(即执行完一个dwg转gdb,再执行另一个dwg转gdb),执行失败 错误描述:首先执行CADToGeodata ...

  9. JavaScript中的Error错误对象与自定义错误类型

    Error Error是JavaScript语言中的一个标准的内置对象,专门用于处理JS开发中的运行时错误. 当我们的JS代码在运行过程中发生错误的话,就会抛出Error对象,整个程序将会中断在错误发 ...

  10. mysql登录错误或者密码错误

    一.mysql登录错误 mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user 'root ...

随机推荐

  1. 【赵渝强老师】Kubernetes平台中日志收集方案

    一.K8s整体日志收集方案 整体的日志收集方案,如下图所示: Filebeat是本地文件的日志数据采集器,可监控日志目录或特定日志文件(tail file),并将它们转发给Elasticsearch或 ...

  2. .net6 中 Blazor PageTitle 设置无效的解决方法

    直接在 razor 页面里添加 <PageTitle>xxx</PageTitle> 标签无效时的解决方法 For using the <PageTitle> ta ...

  3. USB协议详解第11讲(USB描述符-总结)

    描述符回顾总结 1.其实所有的描述符都是USB设备用来描述自己属性及用途的,所以必须在设备端实现对应的描述符,主机会在枚举此设备的时候根据设备实现的描述符去确定设备到底是一个什么样的设备.设备需要的总 ...

  4. 9月《中国数据库行业分析报告》已发布,47页干货带你详览 MySQL 崛起之路!

    为了帮助大家及时了解中国数据库行业发展现状.梳理当前数据库市场环境和产品生态等情况,从2022年4月起,墨天轮社区行业分析研究团队出品将持续每月为大家推出最新<中国数据库行业分析报告>,持 ...

  5. 虚拟dom的优缺点

    虚拟dom 是js模拟的一颗dom树,也是 js 对象 : 虚拟dom 时相对于 真实dom而言的,操作真实 dom 开销太大,降低了性能,所以使用 虚拟 dom 替代真实 dom 完成操作和计算功能 ...

  6. JOI 2018 Final

    A - ストーブ (Stove) 有 \(n\) 个客人将要来访,第 \(i\) 个客人的来访时间为 \([a_i, a_i + 1]\),保证 \(\forall i \in [1, n), a_i ...

  7. keycloak~token有效期与session有效期

    一 refresh_token刷新access_token Keycloak会话管理中,获取到accessToken和refreshToken后,基于accessToken交换用户数据或者参与Keyc ...

  8. Nuxt.js 应用中的 app:templates 事件钩子详解

    title: Nuxt.js 应用中的 app:templates 事件钩子详解 date: 2024/10/18 updated: 2024/10/18 author: cmdragon excer ...

  9. Shell简单入门程序参考

    目录 0 前言 0.1 shell初试 1 程序功能 1.1 显示当前主机名和IP地址. 1.1.1 if 语句 详解 1.2 创建目录或者文件 1.3 修改文件属性 1.3.1 chmod 修改文件 ...

  10. nginx从入门到实战

    概述 异步非阻塞的高性能HTTP和反向代理服务器 nginx的运行架构 1.Master进程 启动检查nginx.conf是否正确 根据配置文件创建.监控worker进程的数量和状态 监听socket ...