我尝试使用Swashbuckle 5.6.0来形容我的asp.net Web API OAuth端点,并尝试了以下解决方案:
How to show WebApi OAuth token endpoint in Swagger
我的问题是,asp.net OAuth授权服务器中接收访问令牌和通过刷新令牌获取新令牌的URL是相同的。
由于“路径”是IDictionary<string, PathItem>
,因此无法将第二个URL添加到Swagger文档路径。
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// get the Token Endpoint from Config
var endpoint = Helpers.GetAppSetting("TokenEndPoint");
// Access Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
@in = "formData"
}
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
@in = "formData"
}
}
}
});
}
}
仅使用不同的参数,是否有可能描述两个指向同一端点的api方法?
答案 0 :(得分:1)
最后,提示“添加无意义的内容”适用于我们的用例。
我还添加了一个新的模型类AuthServerResponseModel
,其中将auth请求的响应映射到其中。
public class AuthServerResponseModel
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
public string audience { get; set; }
}
要使该对象在Swagger中为人所知,必须将该类添加到SchemaRegistry
中。
之后,我可以在响应模式中使用“ @ref”标记来声明我的身份验证请求的响应类型。
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
schemaRegistry.GetOrRegister(typeof(AuthServerResponseModel));
// get the Token Endpoint from Config
string endpoint = "URL-To-The-OAuth-Endpoint";
// Access Token
swaggerDoc.paths.Add(endpoint + "#AccessToken", new PathItem
{
post = new Operation
{
operationId = "AccessToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "DeviceId",
required = false,
@in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", @ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint + "#RefreshToken", new PathItem
{
post = new Operation
{
operationId = "RefreshToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
@in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
@in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", @ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
}
}
使用Swagger Codegen自动生成客户端的效果很好。
答案 1 :(得分:0)
路径是swashbuckle中的字典:
public class SwaggerDocument
{
public readonly string swagger = "2.0";
public Info info;
...
public IDictionary<string, PathItem> paths;
...
}
这就是为什么“键已添加到集合”例外
的原因在大张旗鼓的情况下,我们遵循Open Api规范,并且该路径是带模式的字段:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#patterned-fields
他们清楚地指出,对于这些模式化字段,重复项是“否”:
模式字段可以多次出现,只要每个字段都有唯一的名称即可。
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#specification
最好的选择是将无意义的内容(例如哈希)添加到端点以使其与众不同,这可能是这样的:
swaggerDoc.paths.Add(endpoint + "#Access", new PathItem ...
swaggerDoc.paths.Add(endpoint + "#Refresh", new PathItem ...
gettyimages的家伙如何解决这个问题?
这是一些有趣的发现
他们的大头招json没有那些/oauth2/token
路径
您可以直接在此处进行仔细检查:
https://api.gettyimages.com/swagger/docs/3
这是最新版本的swagger-ui中的swagger json的样子:
http://petstore.swagger.io/?defaultModelsExpandDepth=0&docExpansion=none&url=https://api.gettyimages.com/swagger/docs/3
他们在gettyimages上使用的swagger-ui版本是高度定制的,我认为他们正在使用JS注入其他路径
https://api.gettyimages.com/swagger/ui/ext/GettyImages-Resources-OAuthGrant-js
您也可以做到这一点,这不仅仅是将一些附加内容添加到端点上,还需要做很多工作