当授权标签不包含角色时,我没有获得范围复选框,Ajax 授权请求也不发送范围
I'm not getting a scope checkbox when the Authorize tag doesn't contain roles, Ajax authorization request not sending scope either
更新 2: 如果我从这个更改我的控制器授权标签
[Authorize]
至此
[Authorize(Roles = "Read")]
然后我得到范围 selection 的复选框,并且 ajax 令牌请求包含正确的范围并成功完成。但是,我仍然以红色感叹号结束。 看起来 Swagger 或 Swashbuckle 需要ui角色匹配范围定义?使用 Swashbuckle 时是否可以使用未定义角色的应用程序流程?如果是这样,你如何让它工作? 我是否必须在操作过滤器中手动设置范围 class?如果不在授权标签中列出角色就无法使用 Swashbuckle,那么我需要知道如何在 IdentityServer3 中分配客户端角色。
更新 3
如果我将操作过滤器更改为类似这样的范围,则会出现范围,但在 select 范围并单击授权后,页面会重新加载。 ajax 授权首先发送成功。 这样比较近了,但是授权还是不stick(这里不知道用什么词,但是stick好像可以概括一下。)如何获得stick的授权?
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var scopes = new List<string>() { "Read" };
if (scopes.Any())
{
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", scopes }
};
operation.security.Add(oAuthRequirements);
}
}
原创Post
我正在尝试配置 Swashbuckle 以允许客户端测试受 OAuth2 客户端凭据流保护的 REST 服务。 开关从未出现在页面上,对吗?,但我确实看到一个带有感叹号的红色圆圈,告诉我资源未受保护。我正在使用 nuget 包 Swashbuckle.Core 版本 5.4.0。这里的答案 似乎遵循了我所做的,并且逐字使用了 AssignOAuth2SecurityRequirements class。我没有注入任何 javascript 并且不相信我必须这样做,因为我的授权方案是相当标准的。当我删除控制器上的 Authorize 关键字时,该方法在 Swagger UI 中不再有红色感叹号,我希望这意味着我很接近,但我没有找到丢失的 link .由于这个 Flow 是 "application" 而我只有一个范围,所以我想确保它看起来配置正确并且 clientSecret 加载到正确的位置。
更新 1
我已经能够调试 AJAX 调用,并且可以看到范围未设置,因此未在请求中发送。 为什么没有设置范围?为什么我没有 select 范围的复选框?
这是我的 SwaggerConfig.cs
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "waRougeOneApp");
c.OAuth2("oauth2")
.Description("OAuth2 Client Credentials Grant Flow")
.Flow("application")
.TokenUrl("https://securitydev.rougeone.com/core/connect/token")
.Scopes(scopes =>
{
scopes.Add("Read", "Read access to protected resources");
});
c.IncludeXmlComments(GetXmlCommentsPath());
c.UseFullTypeNameInSchemaIds();
c.DescribeAllEnumsAsStrings();
c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
c.EnableOAuth2Support(
clientId: "client_id",
clientSecret: "client_secret",
realm: "swagger-realm",
appName: "Swagger UI"
);
});
}
protected static string GetXmlCommentsPath()
{
return System.String.Format(@"{0}bin\waRougeOne.xml", System.AppDomain.CurrentDomain.BaseDirectory);
}
}
并且 AssignOAuth2SecurityRequi备注 class 是
public class AssignOAuth2SecurityRequirements : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var authorized = apiDescription.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>();
if (!authorized.Any()) return;
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", Enumerable.Empty<string>()}
};
operation.security.Add(oAuthRequirements);
}
}
我一直试图找到一个客户端凭据流的工作示例但没有成功,所以我不能 100% 确定当一切正常工作时我会看到一个切换按钮。在隐式流程的示例中,如果您将鼠标悬停在红色感叹号圆圈上,您会看到列出的授权类型,单击红色感叹号圆圈会显示列出的范围选项,您可以在其中 select 一个,然后单击授权,它回来时发出蓝色的感叹。
对我来说,我从来没有select一个范围的复选框,但我只定义了一个范围。我究竟做错了什么?我在调试 swagger ui JavaScript 时发现了这一点,它似乎指向拥有它需要的所有数据?
authorizations
:
null
auths
:
Array[1]
0
:
Object
name
:
"oauth2"
type
:
"oauth2"
value
:
Object
description
:
"OAuth2 Client Credentials Grant Flow"
flow
:
"application"
scopes
:
Object
Read
:
"Read access to protected resources"
__proto__
:
Object
tokenUrl
:
"https://security.starrwarrs.com/core/connect/token"
type
:
"oauth2"
__proto__
:
Object
__proto__
:
Object
length
:
1
__proto__
:
Array[0]
这些是我们已经完成和工作的步骤:
- 在 SwaggerConfig 文件中,添加以下设置:
c.OAuth2("oauth2")
.Description("OAuth2 Implicit Grant")
.Flow("implicit")
.AuthorizationUrl(swaggerConfigurations["IssuerUri"].ToString())
.Scopes(scopes =>
{
scopes.Add("user_scope", "Access REST API");
});
属性是:
- 授权方案的名称(上面示例中的 oauth2)
- 授权方案说明
- 流量 – 补助金类型
待使用
- 授权Url – 应该是身份管理系统url的授权Url(例如:
https://auth2.test.com/oauth2/authorize)
- Scopes – 作用域名称
二.在 SwaggerConfig 文件中,也在 swagger ui 配置部分下添加以下设置:
c.EnableOAuth2Support(swaggerConfigurations["ClientId"].ToString(), string.Empty, swaggerConfigurations["RedirectUri"].ToString(), "Swagger", " ", new Dictionary<string, string> { { "resource", GetResources() } });
该方法接受以下参数:
- clientId – 这应该是在安全令牌服务中配置的 swagger 的客户端 ID
- clientSecret – 这应该是客户端密钥。仅在代码授予类型
的情况下才需要 ui 红色
- realm – 这应该是重定向 url(这应该是 [base address] + swagger/ui/o2c-html)
- appName – 这应该是 swagger
- scopeSeperator – 如果只有 scope
,则不需要传递 uired
- additionalQueryStringParams – 这应该有有效受众的列表,这对应于为其颁发令牌的资源。
三。在web api项目中新建一个Operation Filter如下图:
public class CustomOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
string clientId = "clientID";
if (apiDescription != null)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
{
return; // must be an anonymous method
}
}
if (operation != null)
{
if (operation.security == null)
{
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
}
var authRequirements = new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new List<string> { clientId } }
};
operation.security.Add(authRequirements);
}
}
}
此 class 将用于将 OAuth 范围绑定到各个操作
四.在 swagger 配置文件中添加上面的过滤器(见下面的代码)
c.OperationFilter<CustomOperationFilter>();
伏。在安全令牌服务
中配置客户端 ID、密码、重定向 Url 和资源
六。在 Web API 项目中,如果有一个 index.html 被用来注入 API 特定的 UI fields/styles,那么请确保所有 javascript 代码与 index.html 文件的 Swashbuckle 版本保持完整(如位置 - https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/SwaggerUi/CustomAssets/index.html 中提供)
解决方法!!
最后一部分是最难弄清楚的,我最终在 Chrome 开发人员工具的帮助下完成了,该工具在网络标记上显示了一个红色的 X,并显示以下错误消息:
XMLHttpRequest cannot load http://security.RogueOne.com/core/connect/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62561' is therefore not allowed access.
错误消息最终连接了下面的点,直到那时 OAuthComplete 完成 JavaScript 函数将被调用,但没有令牌。网络选项卡显示 "This request has no response data available",但我会在响应 header 中看到 Content-Length,content-type 为 Json。 Fiddler 还显示了看起来(并且)格式正确的响应 JSON.
我在此处描述了这个错误 Swagger UI not parsing reponse which was due to IdentityServer3 correctly not adding a response header of "Access-Control-Allow-Origin:http://localhost:62561“您可以强制 IdentityServer3 发送该错误 header,方法是将您的客户端创建更新为以下内容:
new Client
{
ClientName = "SwaggerUI",
Enabled = true,
ClientId = "swaggerUI",
ClientSecrets = new List<Secret>
{
new Secret("PasswordGoesHere".Sha256())
},
Flow = Flows.ClientCredentials,
AllowClientCredentialsOnly = true,
AllowedScopes = new List<string>
{
"Read"
},
Claims = new List<Claim>
{
new Claim("client_type", "headless"),
new Claim("client_owner", "Portal"),
new Claim("app_detail", "allow")
},
PrefixClientClaims = false
// Add the AllowedCorOrigins to get the Access-Control-Allow-Origin header to be inserted for the following domains
,AllowedCorsOrigins = new List<string>
{
"http://localhost:62561/"
,"http://portaldev.RogueOne.com"
,"https://portaldev.RogueOne.com"
}
}
AllowedCorsOrigins 是我的最后一块拼图。希望这可以帮助面临同样问题的其他人
更新 2: 如果我从这个更改我的控制器授权标签
[Authorize]
至此
[Authorize(Roles = "Read")]
然后我得到范围 selection 的复选框,并且 ajax 令牌请求包含正确的范围并成功完成。但是,我仍然以红色感叹号结束。 看起来 Swagger 或 Swashbuckle 需要ui角色匹配范围定义?使用 Swashbuckle 时是否可以使用未定义角色的应用程序流程?如果是这样,你如何让它工作? 我是否必须在操作过滤器中手动设置范围 class?如果不在授权标签中列出角色就无法使用 Swashbuckle,那么我需要知道如何在 IdentityServer3 中分配客户端角色。
更新 3 如果我将操作过滤器更改为类似这样的范围,则会出现范围,但在 select 范围并单击授权后,页面会重新加载。 ajax 授权首先发送成功。 这样比较近了,但是授权还是不stick(这里不知道用什么词,但是stick好像可以概括一下。)如何获得stick的授权?
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var scopes = new List<string>() { "Read" };
if (scopes.Any())
{
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", scopes }
};
operation.security.Add(oAuthRequirements);
}
}
原创Post
我正在尝试配置 Swashbuckle 以允许客户端测试受 OAuth2 客户端凭据流保护的 REST 服务。 开关从未出现在页面上,对吗?,但我确实看到一个带有感叹号的红色圆圈,告诉我资源未受保护。我正在使用 nuget 包 Swashbuckle.Core 版本 5.4.0。这里的答案
更新 1 我已经能够调试 AJAX 调用,并且可以看到范围未设置,因此未在请求中发送。 为什么没有设置范围?为什么我没有 select 范围的复选框?
这是我的 SwaggerConfig.cs
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "waRougeOneApp");
c.OAuth2("oauth2")
.Description("OAuth2 Client Credentials Grant Flow")
.Flow("application")
.TokenUrl("https://securitydev.rougeone.com/core/connect/token")
.Scopes(scopes =>
{
scopes.Add("Read", "Read access to protected resources");
});
c.IncludeXmlComments(GetXmlCommentsPath());
c.UseFullTypeNameInSchemaIds();
c.DescribeAllEnumsAsStrings();
c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
c.EnableOAuth2Support(
clientId: "client_id",
clientSecret: "client_secret",
realm: "swagger-realm",
appName: "Swagger UI"
);
});
}
protected static string GetXmlCommentsPath()
{
return System.String.Format(@"{0}bin\waRougeOne.xml", System.AppDomain.CurrentDomain.BaseDirectory);
}
}
并且 AssignOAuth2SecurityRequi备注 class 是
public class AssignOAuth2SecurityRequirements : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var authorized = apiDescription.ActionDescriptor.GetCustomAttributes<AuthorizeAttribute>();
if (!authorized.Any()) return;
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", Enumerable.Empty<string>()}
};
operation.security.Add(oAuthRequirements);
}
}
我一直试图找到一个客户端凭据流的工作示例但没有成功,所以我不能 100% 确定当一切正常工作时我会看到一个切换按钮。在隐式流程的示例中,如果您将鼠标悬停在红色感叹号圆圈上,您会看到列出的授权类型,单击红色感叹号圆圈会显示列出的范围选项,您可以在其中 select 一个,然后单击授权,它回来时发出蓝色的感叹。
对我来说,我从来没有select一个范围的复选框,但我只定义了一个范围。我究竟做错了什么?我在调试 swagger ui JavaScript 时发现了这一点,它似乎指向拥有它需要的所有数据?
authorizations
:
null
auths
:
Array[1]
0
:
Object
name
:
"oauth2"
type
:
"oauth2"
value
:
Object
description
:
"OAuth2 Client Credentials Grant Flow"
flow
:
"application"
scopes
:
Object
Read
:
"Read access to protected resources"
__proto__
:
Object
tokenUrl
:
"https://security.starrwarrs.com/core/connect/token"
type
:
"oauth2"
__proto__
:
Object
__proto__
:
Object
length
:
1
__proto__
:
Array[0]
这些是我们已经完成和工作的步骤:
- 在 SwaggerConfig 文件中,添加以下设置:
c.OAuth2("oauth2") .Description("OAuth2 Implicit Grant") .Flow("implicit") .AuthorizationUrl(swaggerConfigurations["IssuerUri"].ToString()) .Scopes(scopes => { scopes.Add("user_scope", "Access REST API"); });
属性是:
- 授权方案的名称(上面示例中的 oauth2)
- 授权方案说明
- 流量 – 补助金类型 待使用
- 授权Url – 应该是身份管理系统url的授权Url(例如: https://auth2.test.com/oauth2/authorize)
- Scopes – 作用域名称
二.在 SwaggerConfig 文件中,也在 swagger ui 配置部分下添加以下设置:
c.EnableOAuth2Support(swaggerConfigurations["ClientId"].ToString(), string.Empty, swaggerConfigurations["RedirectUri"].ToString(), "Swagger", " ", new Dictionary<string, string> { { "resource", GetResources() } });
该方法接受以下参数:
- clientId – 这应该是在安全令牌服务中配置的 swagger 的客户端 ID
- clientSecret – 这应该是客户端密钥。仅在代码授予类型 的情况下才需要 ui 红色
- realm – 这应该是重定向 url(这应该是 [base address] + swagger/ui/o2c-html)
- appName – 这应该是 swagger
- scopeSeperator – 如果只有 scope ,则不需要传递 uired
- additionalQueryStringParams – 这应该有有效受众的列表,这对应于为其颁发令牌的资源。
三。在web api项目中新建一个Operation Filter如下图:
public class CustomOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
string clientId = "clientID";
if (apiDescription != null)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
{
return; // must be an anonymous method
}
}
if (operation != null)
{
if (operation.security == null)
{
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
}
var authRequirements = new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new List<string> { clientId } }
};
operation.security.Add(authRequirements);
}
}
}
此 class 将用于将 OAuth 范围绑定到各个操作
四.在 swagger 配置文件中添加上面的过滤器(见下面的代码)
c.OperationFilter<CustomOperationFilter>();
伏。在安全令牌服务
中配置客户端 ID、密码、重定向 Url 和资源六。在 Web API 项目中,如果有一个 index.html 被用来注入 API 特定的 UI fields/styles,那么请确保所有 javascript 代码与 index.html 文件的 Swashbuckle 版本保持完整(如位置 - https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/SwaggerUi/CustomAssets/index.html 中提供)
解决方法!! 最后一部分是最难弄清楚的,我最终在 Chrome 开发人员工具的帮助下完成了,该工具在网络标记上显示了一个红色的 X,并显示以下错误消息:
XMLHttpRequest cannot load http://security.RogueOne.com/core/connect/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62561' is therefore not allowed access.
错误消息最终连接了下面的点,直到那时 OAuthComplete 完成 JavaScript 函数将被调用,但没有令牌。网络选项卡显示 "This request has no response data available",但我会在响应 header 中看到 Content-Length,content-type 为 Json。 Fiddler 还显示了看起来(并且)格式正确的响应 JSON.
我在此处描述了这个错误 Swagger UI not parsing reponse which was due to IdentityServer3 correctly not adding a response header of "Access-Control-Allow-Origin:http://localhost:62561“您可以强制 IdentityServer3 发送该错误 header,方法是将您的客户端创建更新为以下内容:
new Client
{
ClientName = "SwaggerUI",
Enabled = true,
ClientId = "swaggerUI",
ClientSecrets = new List<Secret>
{
new Secret("PasswordGoesHere".Sha256())
},
Flow = Flows.ClientCredentials,
AllowClientCredentialsOnly = true,
AllowedScopes = new List<string>
{
"Read"
},
Claims = new List<Claim>
{
new Claim("client_type", "headless"),
new Claim("client_owner", "Portal"),
new Claim("app_detail", "allow")
},
PrefixClientClaims = false
// Add the AllowedCorOrigins to get the Access-Control-Allow-Origin header to be inserted for the following domains
,AllowedCorsOrigins = new List<string>
{
"http://localhost:62561/"
,"http://portaldev.RogueOne.com"
,"https://portaldev.RogueOne.com"
}
}
AllowedCorsOrigins 是我的最后一块拼图。希望这可以帮助面临同样问题的其他人