【发布时间】:2017-04-28 04:13:30
【问题描述】:
我正在尝试将 IdentityServer4 与 ASP.NET MVC WebAPI 集成。我想实现基于角色的授权。我正在运行以下项目。
- IdentityServer4 [一个单独的项目]
- WebApi
- Javascript 应用程序 [使用 Extjs]
我已经实现了 ResourceOwnerPassword 流程,我想要做的是,
- 向包含用户名和密码的 WebApi 的 AccountController 发出 post 请求
- 在 AccountController 内部调用 IdentityServer 令牌端点以获取访问令牌并将访问令牌返回给客户端(javascript 应用程序)
- 向包含访问令牌的 WebApi 发出请求。
以上部分我已经成功了,这里是代码
POSTMAN 调用登录
帐户控制器
[ActionName("Login")]
[AllowAnonymous]
[HttpPost]
public async Task<BaseModel> Login(LoginModel model)
{
model.RememberMe = false;
var status = await _security.Login(model.Email, model.Password, model.RememberMe);
if (status.Status == LoginStatus.Succeded)
{
return new BaseModel { success = true, message = "login", data = status.Data };
}
}
安全服务
public async Task<LoginResponse> Login(string userName, string password, bool persistCookie = false)
{
// discover endpoints from metadata
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(userName, password, "api1");
if (tokenResponse.IsError)
{
return new LoginResponse { Status = LoginStatus.Failed, Message = tokenResponse.Error };
}
return new LoginResponse { Status = LoginStatus.Succeded, Data = tokenResponse.Json };
}
保护 API
我在 AccountController 中还有两个操作(仅用于测试),即:
- values() [返回成功并且不需要身份验证]
-
SecureValues [返回成功并需要身份验证]
[HttpGet] public BaseModel values() { return new BaseModel { success = true }; } [Authorize] [HttpGet] public BaseModel SecureValues() { return new BaseModel { success = true }; }
调用 "Values" 操作返回成功,这是非常明显的,调用 "SecureValues" 会得到以下结果
这意味着用户未经过身份验证。
我的IdentityServer4配置如下:
public class Config
{
// scopes define the resources in your system
public static IEnumerable<Scope> GetScopes()
{
return new List<Scope>
{
StandardScopes.OpenId,
StandardScopes.Profile,
new Scope
{
Name = "api1",
Description = "My API",
DisplayName = "API Access",
Type = ScopeType.Resource,
IncludeAllClaimsForUser = true,
Claims = new List<ScopeClaim>
{
new ScopeClaim(ClaimTypes.Name),
new ScopeClaim(ClaimTypes.Role)
}
},
new Scope
{
Enabled = true,
Name = "role",
DisplayName = "Role(s)",
Description = "roles of user",
Type = ScopeType.Identity,
Claims = new List<ScopeClaim>
{
new ScopeClaim(ClaimTypes.Role,false)
}
},
StandardScopes.AllClaims
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
},
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
},
// OpenID Connect implicit flow client (MVC)
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
//flow
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002" },
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
"role"
}
},
//for hybrid flow
new Client
{
ClientId = "mvchybrid",
ClientName ="mvc hybrid client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = {"http://localhost:5003/signin-oidc"},
PostLogoutRedirectUris = {"http://localhost:5003"},
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
StandardScopes.OfflineAccess.Name,
"api1"
}
},
new Client
{
ClientId = "js",
ClientName = "javascript client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser= true,
RedirectUris = {"http://localhost:5004/callback.html"},
PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
AllowedCorsOrigins = {"http://localhost:5004"},
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
"api1",
"role",
StandardScopes.AllClaims.Name
}
},
//aspnet identity client
new Client
{
ClientId = "mvcIdentity",
ClientName = "Mvc Identity Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = {"http://localhost:5005/signin-oidc"},
PostLogoutRedirectUris = {"http://localhost:5005"},
AllowedScopes =
{
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
StandardScopes.OfflineAccess.Name,
"api1"
}
}
};
}
public static List<InMemoryUser> GetUsers()
{
return new List<InMemoryUser>
{
new InMemoryUser
{
Subject = "1",
Username = "alice@yahoo.com",
Password = "password",
Claims = new List<Claim>
{
new Claim("name", "Alice"),
new Claim("website", "https://alice.com"),
new Claim(ClaimTypes.Role,"FreeUser")
}
},
new InMemoryUser
{
Subject = "2",
Username = "bob@yahoo.com",
Password = "password",
Claims = new List<Claim>
{
new Claim("name", "Bob"),
new Claim("website", "https://bob.com"),
new Claim(ClaimTypes.Role,"PaidUser")
}
}
};
}
}
WebApi 配置
public void ConfigureAuth(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServer3.AccessTokenValidation.IdentityServerBearerTokenAuthenticationOptions
{
Authority = "localhost:5000",
RequiredScopes = new[] { "api1" },
ClientId = "ro.client",
ClientSecret = "secret",
PreserveAccessToken = true
});
}
【问题讨论】:
标签: asp.net-mvc asp.net-web-api oauth-2.0 identityserver3 identityserver4