如何使用 OAuth 2.0 实现 REST API 以实现多客户端访问
How to implement REST API with OAuth 2.0 for multiple client access
我有如下要求使用 OAuth 2.0 和 Web Api 实现 REST API。
REST API 应该允许
- 创建、更新、查看和删除订单
- 创建、更新、查看和删除库存
API 应该能够被任何类型的外部客户端使用,例如 Web 应用程序、移动应用程序、windows/web 服务等
外部客户允许的角色:订单管理、库存管理
外部客户端的用户数据(角色、权限)不会被我们的系统管理。
注意:可以有另外两个角色,如内部,外部。因为不允许外部用户使用删除功能。
订单和库存数据将在 SQL 服务器数据库中管理,该数据库已被当前 windows/desktop 应用程序使用。订单、库存来自新 API 应保存在同一数据库中。
问题:
- 我可以使用哪种资助类型?
- 我应该如何管理外部客户的数据(允许的角色、客户 ID、令牌)?我需要为此使用单独的会员数据库吗?我可以为此使用带有新表的现有数据库吗?
Here是Grant选择哪个Client的起点。此外,如果您构建 SPA(根据 link 的措辞,即使它是第一方客户端),我更喜欢隐式授权。如果您对特定客户的特定授权有疑问,请在 Whosebug 上创建一个新问题。
可以使用IdentityServer3 with IdentityServer3.EntityFramework and IdentityServer3.AspNetIdentity。您可以将 IdentityServer 表放在现有数据库中,但我不建议将其用于生产。
您可以使用 Microsoft.Owin.Security.OAuth
提供商。请查看以下示例。
创建新的 Owin Startup
文件并更改 Configuration
方法如下
public void Configuration(IAppBuilder app)
{
var oauthProvider = new OAuthAuthorizationServerProvider
{
OnGrantClientCredentials = async context =>
{
var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
// based on clientId get roles and add claims
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer"));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer2"));
context.Validated(claimsIdentity);
},
OnValidateClientAuthentication = async context =>
{
string clientId;
string clientSecret;
// use context.TryGetBasicCredentials in case of passing values in header
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == "clientId" && clientSecret == "secretKey")
{
context.Validated(clientId);
}
}
}
};
var oauthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/accesstoken"),
Provider = oauthProvider,
AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3),
SystemClock = new SystemClock()
};
app.UseOAuthAuthorizationServer(oauthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
并像这样授权你的API
[Authorize(Roles = "Developer")]
// GET: api/Tests
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
您可以按照以下方式食用,
string baseAddress = "http://localhost/";
var client = new HttpClient();
// you can pass the values in Authorization header or as form data
//var authorizationHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes("clientId:secretKey"));
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationHeader);
var form = new Dictionary<string, string>
{
{"grant_type", "client_credentials"},
{"client_id", "clientId"},
{"client_secret", "secretKey"},
};
var tokenResponse = client.PostAsync(baseAddress + "accesstoken", new FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
var authorizedResponse = client.GetAsync(baseAddress + "/api/Tests").Result;
Token.cs
internal class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
您问题的答案
- 你可以使用
client_credentials
- 在您自己的数据库中为每个客户和内部维护角色
OnGrantClientCredentials
只需通过客户 ID 获取角色并分配为声明。
我有如下要求使用 OAuth 2.0 和 Web Api 实现 REST API。
REST API 应该允许 - 创建、更新、查看和删除订单 - 创建、更新、查看和删除库存
API 应该能够被任何类型的外部客户端使用,例如 Web 应用程序、移动应用程序、windows/web 服务等
外部客户允许的角色:订单管理、库存管理 外部客户端的用户数据(角色、权限)不会被我们的系统管理。
注意:可以有另外两个角色,如内部,外部。因为不允许外部用户使用删除功能。
订单和库存数据将在 SQL 服务器数据库中管理,该数据库已被当前 windows/desktop 应用程序使用。订单、库存来自新 API 应保存在同一数据库中。
问题:
- 我可以使用哪种资助类型?
- 我应该如何管理外部客户的数据(允许的角色、客户 ID、令牌)?我需要为此使用单独的会员数据库吗?我可以为此使用带有新表的现有数据库吗?
Here是Grant选择哪个Client的起点。此外,如果您构建 SPA(根据 link 的措辞,即使它是第一方客户端),我更喜欢隐式授权。如果您对特定客户的特定授权有疑问,请在 Whosebug 上创建一个新问题。
可以使用IdentityServer3 with IdentityServer3.EntityFramework and IdentityServer3.AspNetIdentity。您可以将 IdentityServer 表放在现有数据库中,但我不建议将其用于生产。
您可以使用 Microsoft.Owin.Security.OAuth
提供商。请查看以下示例。
创建新的 Owin Startup
文件并更改 Configuration
方法如下
public void Configuration(IAppBuilder app)
{
var oauthProvider = new OAuthAuthorizationServerProvider
{
OnGrantClientCredentials = async context =>
{
var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
// based on clientId get roles and add claims
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer"));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Developer2"));
context.Validated(claimsIdentity);
},
OnValidateClientAuthentication = async context =>
{
string clientId;
string clientSecret;
// use context.TryGetBasicCredentials in case of passing values in header
if (context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == "clientId" && clientSecret == "secretKey")
{
context.Validated(clientId);
}
}
}
};
var oauthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/accesstoken"),
Provider = oauthProvider,
AuthorizationCodeExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3),
SystemClock = new SystemClock()
};
app.UseOAuthAuthorizationServer(oauthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
并像这样授权你的API
[Authorize(Roles = "Developer")]
// GET: api/Tests
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
您可以按照以下方式食用,
string baseAddress = "http://localhost/";
var client = new HttpClient();
// you can pass the values in Authorization header or as form data
//var authorizationHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes("clientId:secretKey"));
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationHeader);
var form = new Dictionary<string, string>
{
{"grant_type", "client_credentials"},
{"client_id", "clientId"},
{"client_secret", "secretKey"},
};
var tokenResponse = client.PostAsync(baseAddress + "accesstoken", new FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
var authorizedResponse = client.GetAsync(baseAddress + "/api/Tests").Result;
Token.cs
internal class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
您问题的答案
- 你可以使用
client_credentials
- 在您自己的数据库中为每个客户和内部维护角色
OnGrantClientCredentials
只需通过客户 ID 获取角色并分配为声明。