【问题标题】:Mix Windows Authentication and individual accounts in web api在 Web api 中混合 Windows 身份验证和个人帐户
【发布时间】:2017-10-14 02:59:09
【问题描述】:
我有一个使用个人帐户并正确发布令牌的 Web API。我对其进行了修改以接受来自本机应用程序的社交身份验证。
现在,我想为内部员工添加选项,以使用他们的域凭据访问该 API,而不是创建新的用户名和密码。
员工应该调用 api/token 来获取令牌,但是,他们将传入主体,域凭据。
关于如何区分普通用户名和密码以及域凭据以及在哪里进行更改的任何想法?
【问题讨论】:
标签:
c#
oauth-2.0
asp.net-web-api2
【解决方案1】:
我成功了,但我只是想确保我没有让自己陷入安全问题,我已准备好发表任何评论。
首先,我所做的所有更改都在提供程序文件中:ApplicationOAuthProvider.cs:
-
创建新的私有变量来定义客户端是否要使用域登录:
private bool DomainUser = false;
-
修改了负责发布令牌的第一个任务,因此它在请求正文中检查新参数(DomainUser):grant_type=password&username=username&password=password&DomainUser=true:
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
DomainUser = context.Parameters["DomainUser"] == "true";
context.Validated();
}
return Task.FromResult<object>(null);
}
-
修改了验证用户名和密码的任务,所以首先它会检查这是否是对DomainUser的请求,并与域进行身份验证,否则会照常进行:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user;
if (DomainUser && IsValidCredentials(context.UserName, context.Password, "MyDomain"))
user=await PrepareDomainUser(context);
else
user = await userManager.FindAsync(context.UserName, context.Password);
函数 IsValidCredentials 将验证与域的凭据(您需要添加对 System.DirectoryServices.AccountManagement 的引用):
private static bool IsValidCredentials(string Username, string Password, string Domain)
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain))
{
return pc.ValidateCredentials(Username, Password);
}
}
如果这是第一次,PrepareDomainUser 将创建应用程序用户,无需密码:
private async Task<ApplicationUser> PrepareDomainUser(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindByEmailAsync(context.UserName);
if (user == null)
{
user = new ApplicationUser() { UserName = context.UserName, Email = context.UserName };
IdentityResult result = await userManager.CreateAsync(user);
}
return user;
}