更新2:如果我从此处更改我的控制器授权标记
[Authorize]
到这个
[Authorize(Roles = "Read")]
然后我得到范围选择的复选框,ajax令牌请求包含正确的范围并成功完成。然而,我仍然以红色感叹号结束。 看起来Swagger或Swashbuckle要求角色与范围定义匹配?使用Swashbuckle时是否可以使用没有定义角色的应用程序流?如果是这样,你怎么做到这一点?我是否必须在操作过滤器类中手动设置范围?如果在Authorize标签中没有列出Roles的情况下无法使用Swashbuckle,那么我需要知道如何在IdentityServer3中分配客户端角色。
更新3 如果我将操作过滤器更改为这样的范围,则会显示范围,但在选择范围并单击“授权”后,页面将重新加载。首先成功发送了ajax授权。 这是更接近的,但授权仍然没有坚持(不确定在这里使用什么术语,但坚持似乎总结了。)我如何获得授权坚持?
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);
}
}
原帖 我正在尝试配置Swashbuckle以允许客户端测试受OAuth2客户端凭据流保护的REST服务。 切换页面上永远不会出现切换,是吗?,但我确实得到一个带有感叹号的红色圆圈,告诉我资源没有受到保护。我正在使用nuget包Swashbuckle.Core版本5.4.0。这里的答案Enable Oauth2 client credentials flow in Swashbuckle似乎遵循我所做的,并逐字使用了AssignOAuth2SecurityRequirements类。我没有注入任何JavaScript,并且不相信我必须,因为我的授权方案是相当标准的。当我删除Controller上的授权关键字时,该方法在Swagger UI中不再有红色感叹号,我希望这意味着我很接近,但我找不到丢失的链接。由于这个Flow是“应用程序”而我只有一个作用域,我想确保它看起来配置正确并且clientSecret加载到正确的位置。
更新1 我已经能够调试AJAX调用,并且可以看到未设置范围,因此未在请求中发送。 为什么没有设置范围?为什么我没有选中范围的复选框?
这是我的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);
}
}
AssignOAuth2SecurityRequirements类是
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%确定当一切正常时我会看到一个切换按钮。在隐藏流程的示例中,如果将鼠标悬停在红色感叹圈上,则会看到列出的授权类型,单击红色感叹号圆圈会显示列出的范围选项,您可以在其中选择一个,然后单击授权,然后返回蓝色感叹。
对我来说,我从来没有选中范围的复选框,但我只定义了一个范围。我究竟做错了什么?我在调试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]
答案 0 :(得分:1)
这些是我们已经完成和工作的步骤:
c.OAuth2("oauth2") .Description("OAuth2 Implicit Grant") .Flow("implicit") .AuthorizationUrl(swaggerConfigurations["IssuerUri"].ToString()) .Scopes(scopes => { scopes.Add("user_impersonation", "Access REST API"); });
属性是:
II。在SwaggerConfig文件中,还可以在swagger ui配置部分下添加以下设置:
c.EnableOAuth2Support(swaggerConfigurations["ClientId"].ToString(), string.Empty, swaggerConfigurations["RedirectUri"].ToString(), "Swagger", " ", new Dictionary<string, string> { { "resource", WebApi.Utility.GetAudiences().First() } });
该方法接受以下参数:
III。在web api项目中创建一个新的Operation Filter,如下所示:
public class AssignOperationFilters : 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);
}
}
}
此类将用于将OAuth范围绑定到各个操作
IV。在swagger配置文件中添加上面的过滤器(参见下面的代码)
c.OperationFilter<AssignOperationFilters>();
诉在安全令牌服务中配置客户端ID,密钥,重定向URL和资源
VI。在Web API项目中,如果有一个index.html用于注入特定于API的UI字段/样式,那么请确保所有的javascript代码都保留在原始版本的index.html文件的Swashbuckle中(如location - https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/SwaggerUi/CustomAssets/index.html)
答案 1 :(得分:1)
<强>解决方案!! 强> 最后一部分是最难以弄清楚的,我最终在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.
错误消息最终连接了下面的点,直到那时将调用on OAuthComplete完整的JavaScript函数,但没有令牌。网络选项卡显示&#34;此请求没有可用的响应数据&#34;,但我在响应标头中看到内容类型为Json的Content-Length。 Fiddler还展示了看起来像(并且是)JSON的反应。
我在这里描述了这个错误Swagger UI not parsing reponse,这是由于IdentityServer3正确地没有添加&#34; Access-Control-Allow-Origin:http://localhost:62561&#34;的响应头。您可以通过将客户端创建更新为以下内容来强制IdentityServer3发送该标头:
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是我拼图的最后一块。希望这可以帮助面临同样问题的其他人