我想就.NET Web API項目中的角色和作用域之間的區別做一個更清晰的描述。這比其他任何方面都更具有最佳方法的問題,我發現自己對如何最好地授權希望訪問我的API的用戶有點困惑。我來自.NET MVC背景,所以我熟悉角色,我想知道是否同樣的方法適用於Web API框架。我很難將範圍放在圖片中,以及如何使用它們來允許使用特定客戶端ID的用戶訪問。範圍與訪問權限類似嗎?爲了說明我的困惑,讓我們用這個例子:.Net Web API 2,OWIN和OAuth:範圍和角色。有什麼區別?
Client A
Native app: displays event calendar
Role: Event
User login required? No
Allowed scopes: Read events
Client B
Web app: shows next upcoming event, displays registrant names
Role: Event
User login required? Yes
Allowed scopes: Read events, read registrants
Client C
Native app: registers a person for an event
Role: Registrant
User login required? Yes
Allowed scopes: Read events, read registrants, write registrants
基本上我想知道如果我的上述使用範圍的是正確的,什麼是最好的辦法是給予資源所有者憑證。我正在使用基於令牌的身份驗證,如Taiseers tutorial中所述。下面是我目前不完全的代碼片段,將採取的確認(validate)要求照顧客戶端和範圍:
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
ApiClient client = null;
string clientId = string.Empty;
string clientSecret = string.Empty;
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
context.TryGetFormCredentials(out clientId, out clientSecret);
if (context.ClientId == null)
{
context.Validated();
context.SetError("invalid_clientId", "ClientId should be sent.");
return Task.FromResult<object>(null);
}
using (ApiClientRepo _clientRepo = context.OwinContext.GetUserManager<ApiClientRepo>())
{
client = _clientRepo.FindClient(context.ClientId);
}
if (client == null)
{
context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId));
return Task.FromResult<object>(null);
}
// Validate client secret
if (string.IsNullOrWhiteSpace(clientSecret))
{
context.SetError("invalid_secret", "Client secret should be sent.");
return Task.FromResult<object>(null);
}
else
{
WPasswordHasher passwordHasher = new WPasswordHasher();
PasswordVerificationResult passwordResult = passwordHasher.VerifyHashedPassword(client.SecretHash, clientSecret);
if (passwordResult == PasswordVerificationResult.Failed)
{
context.SetError("invalid_secret", "Client secret is invalid.");
return Task.FromResult<object>(null);
}
}
if (!client.Active)
{
context.SetError("invalid_clientId", "Client is inactive.");
return Task.FromResult<object>(null);
}
context.OwinContext.Set<int>("as:clientRepoId", client.Id);
context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin);
context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTime.ToString());
context.Validated();
return Task.FromResult<object>(null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
IApiUser user = null;
string scope = null;
// Get parameters sent in body
Dictionary<string, string> body = context.Request.GetBodyParameters();
// Get API scope
body.TryGetValue("scope", out scope);
if (scope == null)
{
context.Validated();
context.SetError("invalid_scope", "Invalid requested scope.");
return;
}
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
// At this point I got the requested scope.
// What should I do with it?
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
// create claims identity based on user info
ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, user.FirstName + " " + user.LastName));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Username));
identity.AddClaim(new Claim(ClaimTypes.Role, scope));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId
},
{
"userName", context.UserName
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
提前感謝所有的想法,建議和想法!
感謝您的解釋。我明白,就你而言,你使用範圍作爲每個資源的權限,所以非常精細。我看了一下[Google的作用域文檔](https://developers.google.com/identity/protocols/googlescopes),看起來你可以像他們那樣做。那麼如何驗證請求是否具有資源x的適當範圍?你有自定義操作過濾器來做到這一點? – Sebbo
我不會說它是一個許可持續,也許是一個客戶端訪問用戶資源的權限行爲。 事實上,我已經使用自定義過濾器驗證了範圍,並在每個WebApi方法上定義了具有所需範圍的自定義屬性。 – Max
啊,是的,這是有道理的。我相信我現在對Web API的作用域和角色有更清晰的瞭解。我在想自定義過濾器來檢查所需的範圍。謝謝! – Sebbo