访问受IdentityServer3保护的API时出现错误401

编程入门 行业动态 更新时间:2024-10-19 13:30:15
本文介绍了访问受IdentityServer3保护的API时出现错误401的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

尝试从受IdentityServer3保护的API访问资源时遇到401错误.

I'm getting a 401 error when I try to access a resource from an API protected by IdentityServer3.

我可以登录并从IdentityServer3的主机应用程序中静静地获取 access_token ,但是我不能使用 access_token 来消耗此资源.

I can log in and get the access_token quietly from the Host application of IdentityServer3, but I cannot use the access_token to consume this resource.

我在 Startup 类中配置了IdentityServer的主机,如下所示:

I configured my Host of IdentityServer in Startup class like this:

public void Configuration(IAppBuilder app) { Log.Logger = new LoggerConfiguration() .WriteTo.Trace() .CreateLogger(); AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject; JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>(); // Configure IdentityServer3 app.Map("/identity", configuration => { configuration.UseIdentityServer(new IdentityServerOptions { SiteName = "IdentityServer3 Sample", SigningCertificate = LoadCertificate(), Factory = ServiceFactory.Create(), RequireSsl = true, CspOptions = new CspOptions { Enabled = true, FontSrc = "fonts.googleapis" }, AuthenticationOptions = new AuthenticationOptions { EnablePostSignOutAutoRedirect = true, } }); }); }

在我的 ServiceFactory 类中,我有:

public static IdentityServerServiceFactory Create() { var factory = new IdentityServerServiceFactory { ScopeStore = new Registration<IScopeStore>( new InMemoryScopeStore(Scopes.GetScopes())), ClientStore = new Registration<IClientStore>( new InMemoryClientStore(Clients.GetClients())), CorsPolicyService = new Registration<ICorsPolicyService>( new DefaultCorsPolicyService {AllowAll = true}) }; //factory.UseInMemoryUsers(Users.GetUsers()); ConfigureServices(factory); return factory; } private static void ConfigureServices(IdentityServerServiceFactory factory) { factory.UserService = new Registration<IUserService, UserService>(); factory.Register(new Registration<BaseContext>(resolver => new BaseContext())); factory.Register(new Registration<AppUserManager>(resolver => new AppUserManager( new UserStore<User>(resolver.Resolve<BaseContext>())))); }

范围:

return new List<Scope> { StandardScopes.OpenId, StandardScopes.Profile, StandardScopes.OfflineAccess, new Scope { Enabled = true, Name = "roles", Type = ScopeType.Identity, IncludeAllClaimsForUser = true, Claims = new List<ScopeClaim> { new ScopeClaim("role") } }, new Scope { Enabled = true, Name = "ro", Type = ScopeType.Resource, IncludeAllClaimsForUser = true, Claims = new List<ScopeClaim> { new ScopeClaim("role") } } };

和客户:

return new List<Client> { new Client { Enabled = true, ClientName = "Hibrid Flow Client", ClientId = AppIdentityConstants.ClientIdForHibridFlow, Flow = Flows.Hybrid, RequireConsent = false, AccessTokenType = AccessTokenType.Reference, UpdateAccessTokenClaimsOnRefresh = true, ClientSecrets = new List<Secret> { new Secret(AppIdentityConstants.ClientSecret.Sha256()) }, AllowedScopes = new List<string> { Constants.StandardScopes.OpenId, Constants.StandardScopes.Profile, Constants.StandardScopes.Email, Constants.StandardScopes.Roles, Constants.StandardScopes.OfflineAccess, }, RedirectUris = new List<string> { AppIdentityConstants.IdentityAddress, AppIdentityConstants.CRMAddress }, PostLogoutRedirectUris = new List<string> { AppIdentityConstants.IdentityAddress, AppIdentityConstants.CRMAddress }, LogoutSessionRequired = true }, new Client { Enabled = true, ClientName = "Resource Owner Client", ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow, Flow = Flows.ResourceOwner, RequireConsent = false, AccessTokenType = AccessTokenType.Jwt, UpdateAccessTokenClaimsOnRefresh = true, AccessTokenLifetime = 3600, ClientSecrets = new List<Secret> { new Secret(AppIdentityConstants.ClientSecret.Sha256()) }, AllowedScopes = new List<string> { Constants.StandardScopes.OpenId, Constants.StandardScopes.Profile, Constants.StandardScopes.Email, Constants.StandardScopes.Roles, Constants.StandardScopes.OfflineAccess, "ro" }, AllowAccessTokensViaBrowser = true, AbsoluteRefreshTokenLifetime = 86400, SlidingRefreshTokenLifetime = 43200, RefreshTokenUsage = TokenUsage.OneTimeOnly, RefreshTokenExpiration = TokenExpiration.Sliding }, };

这是IdentityServer3主机应用程序的源代码.

This is the source code for the Host Application of IdentityServer3.

现在,我将向您展示如何设置API. 这是我的启动类:

And now I'll show you how I've set up my API. This is my Startup class:

public void Configuration(IAppBuilder app) { JwtSecurityTokenHandler.InboundClaimTypeMap.Clear(); app.UseIdentityServerBearerTokenAuthentication( new IdentityServerBearerTokenAuthenticationOptions { Authority = AppIdentityConstants.IdentityBaseAddress, RequiredScopes = new[] { "ro", "offline_access" }, ClientId = AppIdentityConstants.ClientIdForResourceOwnerFlow, ClientSecret = AppIdentityConstants.ClientSecret, }); }

AppIdentityConstants.IdentityBaseAddress是localhost:44342/identity.

然后,在 Global.asax.cs 中,我将这些配置称为:

And, in Global.asax.cs I call these configurations:

public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services config.Formatters.Remove(config.Formatters.XmlFormatter); var formatters = GlobalConfiguration.Configuration.Formatters; var jsonFormatter = formatters.JsonFormatter; var settings = jsonFormatter.SerializerSettings; #if DEBUG settings.Formatting = Formatting.Indented; #endif settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // Web API routes config.MapHttpAttributeRoutes(); config.EnableCors(new EnableCorsAttribute("*", "*", "*")); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }

和 AuthorizeAttribute 过滤器:

public class FilterConfig { public static void RegisterGlobalFilters(HttpConfiguration configuration) { configuration.Filters.Add(new AuthorizeAttribute()); } }

要进行测试,我做了以下工作:

To test I did the following:

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> </head> <body> <script src="bower_components/jquery/dist/jquery.min.js"></script> <script> function done(response) { console.log(response); } function always(response) { console.log("always"); } function fail(response) { console.log("fail"); } var custom = { client_id: "ro", client_secret: "client_secret", scope: "ro offline_access", }; $(function () { var settings = { "async": true, "crossDomain": true, "url": "localhost:44342/identity/connect/token", "method": "POST", "headers": { "content-type": "application/x-www-form-urlencoded", "cache-control": "no-cache" }, "data": { "client_id": custom.client_id, "client_secret": custom.client_secret, "scope": custom.scope, "username": "user@test", "password": "123456", "grant_type": "password" } } $.ajax(settings).done(function (response){ done(response); checkStatus(response.access_token); }).always(always).fail(fail); function checkStatus(access_token) { var settings2 = { "async": true, "crossDomain": true, "url": "localhost:44352/api/importer/status", "method": "GET", xhrFields: { withCredentials: true }, "headers": { "Authorization": "Bearer " + access_token, "cache-control": "no-cache" } } $.ajax(settings2).done(done).always(always).fail(fail); } }); </script> </body> </html>

第一个用于获取访问数据(包括acess_token)的请求已成功完成.

The first request, which is to obtain the access data, including the acess_token, is done successfully.

但是对API发出的第二个请求返回401错误. 正如我之前所展示的, API受AuthorizeAttribute保护.

But the second request, which is made to the API, returns a 401 error. And as I showed earlier, the API is protected with the AuthorizeAttribute.

怎么了?

推荐答案

如果调试checkStatus函数,acessData参数是否具有access_token属性?

If you debug the checkStatus function, does the acessData parameter have an access_token property?

如果是,那么您是否在Web API项目中安装了Microsoft.Owin.Host.SystemWeb NuGet软件包?可能发生的情况是您的OWIN管道未执行,因为您缺少该软件包.因此,访问令牌不会转换为身份,并且请求保持未经身份验证,这可以解释HTTP 401响应.

If so, then did you install the Microsoft.Owin.Host.SystemWeb NuGet package in your Web API project? What could happen is that your OWIN pipeline is not executed because you're missing that package. So the access token is not transformed into an identity, and the request stays unauthenticated, which could explain the HTTP 401 response.

更多推荐

访问受IdentityServer3保护的API时出现错误401

本文发布于:2023-11-17 02:06:13,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1608412.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:出现错误   API

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!