gpt4 book ai didi

c# - 使用 IdentityServer 向特定客户端验证特定用户

转载 作者:行者123 更新时间:2023-11-30 21:47:19 27 4
gpt4 key购买 nike

我正在使用 IdentityServerV3 对少数客户端的用户进行身份验证。我在配置 IdentityServer 时遇到问题,特定的 user 必须能够登录到特定的“客户端”。

让我们来看下面的场景:

我有 2 个客户端 -> client1, client2。我有 3 个用户 -> user1user2user3

user1user2 只能访问 client1。而 user3 可以单独访问 client2

当我尝试使用 user3 登录到 client1 时,身份服务器验证成功。我不想要。

public static class Clients
{
public static IEnumerable<Client> Get()
{
return new[]
{
new Client
{
Enabled = true,
ClientName = "MVC Client",
ClientId = "mvc",
Flow = Flows.Hybrid,

RedirectUris = new List<string>
{
"https://localhost:44319/"
}
},
new Client
{
Enabled = true,
ClientName = "MVC Client 2",
ClientId = "mvc2",
Flow = Flows.Hybrid,

RedirectUris = new List<string>
{
"https://localhost:44319/"
}
}
};
}
}

用户是:

public static class Users
{
public static List<InMemoryUser> Get()
{
return new List<InMemoryUser>
{
new InMemoryUser
{
Username = "bob",
Password = "secret",
Subject = "1",

Claims = new[]
{
new Claim(Constants.ClaimTypes.GivenName, "Bob"),
new Claim(Constants.ClaimTypes.FamilyName, "Smith")
}
},
new InMemoryUser
{
Username = "rob",
Password = "secret",
Subject = "2",

Claims = new[]
{
new Claim(Constants.ClaimTypes.GivenName, "Rob"),
new Claim(Constants.ClaimTypes.FamilyName, "Thompson")
}
},
new InMemoryUser
{
Username = "Jerry",
Password = "secret",
Subject = "3",

Claims = new[]
{
new Claim(Constants.ClaimTypes.GivenName, "Jerry"),
new Claim(Constants.ClaimTypes.FamilyName, "Smith")
}
}
};
}
}

现在 OWIN 启动类是:

public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/identity", idsrvApp =>
{
idsrvApp.UseIdentityServer(new IdentityServerOptions
{
SiteName = "Embedded IdentityServer",
SigningCertificate = LoadCertificate(),

Factory = InMemoryFactory.Create(
users : Users.Get(),
clients: Clients.Get(),
scopes : StandardScopes.All)
});
});
}

X509Certificate2 LoadCertificate()
{
return new X509Certificate2(
string.Format(@"{0}\bin\identityServer\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test");
}
}

我不明白 IdentityServer 如何知道哪个用户 bleongs 到哪个客户端。 IdentityServer 不支持我的场景,还是我遗漏了什么。

更新

    public class LocalRegistrationUserService : UserServiceBase
{
public class CustomUser
{
public string Subject { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public List<Claim> Claims { get; set; }
}

public static List<CustomUser> Users = new List<CustomUser>();

public string ClientId { get; set; }

public override Task AuthenticateLocalAsync(LocalAuthenticationContext context)
{
var user = Users.SingleOrDefault(x => x.Username == context.UserName && x.Password == context.Password);
if (user != null)
{
context.AuthenticateResult = new AuthenticateResult(user.Subject, user.Username);
}

return Task.FromResult(0);
}
}

在注册用户时,我将他重定向到 Identity Server Host 中的 Controller

 public class LocalRegistrationController : Controller
{
[Route("core/localregistration")]
[HttpGet]
public ActionResult Index(string signin)
{
return View();
}

[Route("core/localregistration")]
[HttpPost]
public ActionResult Index(string signin, LocalRegistrationModel model)
{
var ctx = Request.GetOwinContext();
if (ModelState.IsValid)
{
var user = new LocalRegistrationUserService.CustomUser
{
Username = model.Username,
Password = model.Password,
Subject = Guid.NewGuid().ToString(),
Claims = new List<Claim>()
};
LocalRegistrationUserService.Users.Add(user);
user.Claims.Add(new Claim(Constants.ClaimTypes.GivenName, model.First));
user.Claims.Add(new Claim(Constants.ClaimTypes.FamilyName, model.Last));

return Redirect("~/core/" + Constants.RoutePaths.Login + "?signin=" + signin);
}

return View();
}
}

startup.cs

 app.Map("/core", coreApp =>
{
var factory = new IdentityServerServiceFactory()
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get());

// different examples of custom user services
//var userService = new RegisterFirstExternalRegistrationUserService();
//var userService = new ExternalRegistrationUserService();

var userService = new LocalRegistrationUserService();

// note: for the sample this registration is a singletone (not what you want in production probably)
factory.UserService = new Registration<IUserService>(resolver => userService);
factory.ViewService = new Registration<IViewService, CustomViewService>();
var options = new IdentityServerOptions
{
SiteName = "Identity Server 3",

SigningCertificate = Certificate.Get(),
Factory = factory,

AuthenticationOptions = new AuthenticationOptions
{
IdentityProviders = ConfigureAdditionalIdentityProviders,
LoginPageLinks = new LoginPageLink[] {
new LoginPageLink{
Text = "Register",
// Href = "~/externalregistration",
Href = "~/localregistration",
//Href = "localregistration"
},
new LoginPageLink{
Text = "Forgot Password?",
Href = "~/forgotpassword",
//Href = "localregistration"
}
}
},

EventsOptions = new EventsOptions
{
RaiseSuccessEvents = true,
RaiseErrorEvents = true,
RaiseFailureEvents = true,
RaiseInformationEvents = true
}
};

coreApp.UseIdentityServer(options);
});

我需要了解在注册时将 user 映射到 client 的最佳方法,并确保用户只能登录到该客户端,而不能登录任何其他客户端,即使usernamepassword 对于该用户的所有客户端都是相同的。

最佳答案

如果您在您的 id_token 中提供自定义声明,名为 application_access,其值为用户有权访问的应用程序/客户端,会怎样?其中可能有很多。您可以在您的 IUserService 实现中添加此自定义声明,并以与映射其他用户特定声明相同的方式映射它。

然后,在您的客户端中,检查该特定声明并检查登录用户是否具有针对该特定客户端的特定值的声明。

https://github.com/IdentityModel/Thinktecture.IdentityModel.45/blob/master/IdentityModel/Thinktecture.IdentityModel/Authorization/WebApi/ScopeAttribute.cs

(标记:RequireScope 用于访问 token 和 API,但您已了解总体思路)

关于c# - 使用 IdentityServer 向特定客户端验证特定用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38529987/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com