我申请调用使用 IdentityServer 保护的 Web API 的代码如下。
var accessToken = await HttpContext.GetTokenAsync("access_token");
var data = new List<WeatherForecast>();
using (var client = new HttpClient())
{
client.SetBearerToken(accessToken);
var result = await client.GetAsync("https://localhost:6001/WeatherForecast");
if (result.IsSuccessStatusCode)
{
var model = await result.Content.ReadAsStringAsync();
data = JsonConvert.DeserializeObject<List<WeatherForecast>>(model);
}
else
{
throw new Exception("Failed to get Data from API");
}
}
此代码失败,日志中用户未通过身份验证。这段代码实际上是在用户通过 IdentityServer 进行身份验证后执行的。所以代码行:
var accessToken = await HttpContext.GetTokenAsync("access_token");
正在为我提供 accessToken。但是没有调用Web API,为什么呢?? 我在 Postman 上测试了使用相同的访问令牌调用 web api,它能够调用 web api。
所以我认为我的 OpenID Connect 设置有问题。我使用的 OpenID 连接设置是:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:5001";
options.Audience = "Bond";
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "xena";
options.ResponseType = "code";
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("fullaccess");
options.SaveTokens = true;
});
我在 OpenID Connect 中尝试了许多设置,但似乎没有任何效果。我正在向您展示工作和问题。
<块引用>这里可以看到认证部分:
<块引用>在这里你可以看到问题。
身份验证后,我访问调用 Web API 的 URL。我用这一行得到令牌:
var accessToken = await HttpContext.GetTokenAsync("access_token")
但是当我使用令牌进行 api 调用时,我在控制台日志中得到 Showing login: User is not authentication 。见下图:
问题是用户已经通过身份验证,否则我无法获得访问令牌。
我深入研究了这个问题,并在 api 调用代码上设置了一个断点。我发现对api的调用被重定向到这个url:
<块引用>帐户/登录?RETURNURL =%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dzorro%26redirect_uri%3Dhttps%253A%252F%252Flocalhost%253A6001%252Fsignin-OIDC%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520fullaccess%26code_challenge% 3Dwd31qWo2SpjTuncroM6qkWSvhFg-rKDVcicPOrp3-6E%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637629779176334831.MTUwZjRlODgtZmJhYi00Y2I3LWFlYmQtNGYzNWViZmM1NWNjOWI1NDg4YTItMGI5Yy00MTk3LTk0OTQtMDIxMWI5YTg1NGIw%26state%3DCfDJ8Cuukidn-CJOlLfkzyfYd36FVs9F-zMJ_0v67GE7qgtpnN8Zd10Gnkwbhm2VgMnLCt3pihVGA3jhXFF2rYrBaj8z-j1muaq8BgUcM4Ay3yjR1i2D4gm3JrXtAUGQAulW8CqC3XWbXvS8b3U8srEXVFP2qGW91jejBVJ9YCc1v-3gTYaRmRuf45DM3Kx1bDML7Yz7s1wKyXjvSE5aS5Bq78az3gXpqOC7GIciNJ2UELFtDSJF14GEYwtHM53Ehv3p_XvU86RCYwzH9jU9CzoCeIx6ScKbRi0hTp9nybNgj3PlOvzMZWg4taxiOK3yKxroFEK_GGAY9oK_ZzsRodVcoJp-2BGA_yceJbU0GeoPic111cjUC4_ml1r_gBiq-o7dDBWRRJsFyScGVRNDj8vyL7k%26X-客户SKU%3DID_NETSTANDARD2_0%26X-客户-VER% 3D6.7.1.0
很明显,应用程序得出结论,我没有通过身份验证,因此我无法进行 api 调用。但是我已经认证过了,请问怎么解决?
答案 0 :(得分:1)
我的建议是将WEB API放在自己的服务上,遵循关注点分离的原则。当您混合使用 IdentityServer 和 Web 应用程序以及 API 时,您就是在自找麻烦。
答案 1 :(得分:0)
据我所知,text.txt
方法将根据身份验证方案获取令牌。
我建议您可以尝试指定身份验证方案,然后重试。如下图:
HttpContext.GetTokenAsync
答案 2 :(得分:0)
我通过将 Web API 中的 [Authorize] 属性更改为以下内容找到了解决方案:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
然后还在客户端项目(包含 Web API)的 Starup.cs 上添加授权。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme);
// other authorization of oidc which is given in the question itself.