MVC 5 反向代理身份验证并使用角色,仅使用用户名
MVC 5 Reverse Proxy Authentication and make use of Roles, by using the username only
我有一个 MVC 5 网络应用程序。目前该应用使用个人账户登录。还有用于授权的角色。用户使用他们的用户名和密码登录。
问题是这样的。我需要对通过反向代理发出的用户请求进行身份验证和授权。
- 用户向应用发出请求(反向代理 url)
http://myapp.domain.com
- 反向代理将进行额外调用并验证用户是否有权访问应用程序内容。 (为简单起见从图表中删除)。
- 如果用户一切正常,调用将重定向到实际的 MVC 应用程序,其中请求将包含 header 和用户名。
- MVC 必须检查请求是否来自反向代理(这不是问题,IP 检查,加上一些作为 headers 发送的密钥。)
- MVC 应该读取请求 header,获取用户名,根据他拥有的一个或多个角色对其进行身份验证和授权。
- 如果请求不是来自反向代理,则拒绝请求;如果用户没有适当的角色,则拒绝请求。示例用户的角色是访客,但他正在尝试访问管理员角色内容。
我的问题是当只有用户名存在时请求的身份验证和授权。
由于应用程序已经使用用户名和密码进行身份验证,我正在考虑执行以下操作:
- 反向代理会将请求发送到https://realapp.domain.com/account/login。
- 在从帐户控制器登录的操作中,我可以实现读取请求并从 header
获取用户名的逻辑
- 此时我们知道用户 X 已通过身份验证,因为反向代理和其他系统将对此进行检查。所以基本上所有到达的请求都被认为是安全的(来自反向代理服务器)
- 如果数据库中不存在用户名(第一次调用应用程序),MVC 应用程序将使用虚拟密码 (Password123) 创建用户。
- 如果用户名存在于数据库中,则使用用户名和虚拟密码 Password123 登录
var result = await SignInManager.PasswordSignInAsync("username", "Password123", false, shouldLockout: false);
- 用户已通过身份验证和授权。
基本上我的想法是为每个用户设置相同的密码,以便在应用程序中对他们进行身份验证并使用角色。
你怎么看?
因为身份是基于声明的。您不需要任何密码甚至任何用户对象来验证用户。所以在 Identity 中使用存储也是完全可选的。您只需要创建一些声明并根据这些声明授权您的用户。考虑这个简单的例子作为线索:
// imaging this action is called by proxy
public ActionResoult Login()
{
// this custom method extract username from header and check IP and more
var username=_myUserManager.GetUserName();
if(username!=null)
{
// optionally you have own user manager which returns roles from username
// no matter how you store users and roles
string[] roles=_myUserManager.GetUserRoles(username);
// user is valid, going to authenticate user for my App
var ident = new ClaimsIdentity(
new[]
{
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, username),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
// an optional claim you could omit this
new Claim(ClaimTypes.Name, username),
// populate assigned user's role form your DB
// and add each one as a claim
new Claim(ClaimTypes.Role, roles[0]),
new Claim(ClaimTypes.Role, roles[1]),
// and so on
},
DefaultAuthenticationTypes.ApplicationCookie);
// Identity is sign in user based on claim don't matter
// how you generated it
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
// auth is succeed, without needing any password just claim based
return RedirectToAction("MyAction");
}
// invalid user
ModelState.AddModelError("", "We could not authorize you :(");
return View();
}
现在我们无需任何密码即可授权我们的用户,因此我们也可以使用 Authorize
过滤器:
[Authorize]
public ActionResult Foo()
{
}
// since we injected user roles to Identity we could do this as well
[Authorize(Roles="admin")]
public ActionResult Foo()
{
// since we injected our authentication mechanism to Identity pipeline
// we have access current user principal by calling also
// HttpContext.User
}
注意:您的代理必须处理您的应用生成的 cookie 并将它们正确地传送给您的用户。由于您的应用程序基于 cookie。
您可以下载Token Based Authentication Sample from my Github repo and also read 最接近您的场景。
我有一个 MVC 5 网络应用程序。目前该应用使用个人账户登录。还有用于授权的角色。用户使用他们的用户名和密码登录。
问题是这样的。我需要对通过反向代理发出的用户请求进行身份验证和授权。
- 用户向应用发出请求(反向代理 url)
http://myapp.domain.com
- 反向代理将进行额外调用并验证用户是否有权访问应用程序内容。 (为简单起见从图表中删除)。
- 如果用户一切正常,调用将重定向到实际的 MVC 应用程序,其中请求将包含 header 和用户名。
- MVC 必须检查请求是否来自反向代理(这不是问题,IP 检查,加上一些作为 headers 发送的密钥。)
- MVC 应该读取请求 header,获取用户名,根据他拥有的一个或多个角色对其进行身份验证和授权。
- 如果请求不是来自反向代理,则拒绝请求;如果用户没有适当的角色,则拒绝请求。示例用户的角色是访客,但他正在尝试访问管理员角色内容。
我的问题是当只有用户名存在时请求的身份验证和授权。
由于应用程序已经使用用户名和密码进行身份验证,我正在考虑执行以下操作:
- 反向代理会将请求发送到https://realapp.domain.com/account/login。
- 在从帐户控制器登录的操作中,我可以实现读取请求并从 header 获取用户名的逻辑
- 此时我们知道用户 X 已通过身份验证,因为反向代理和其他系统将对此进行检查。所以基本上所有到达的请求都被认为是安全的(来自反向代理服务器)
- 如果数据库中不存在用户名(第一次调用应用程序),MVC 应用程序将使用虚拟密码 (Password123) 创建用户。
- 如果用户名存在于数据库中,则使用用户名和虚拟密码 Password123 登录
var result = await SignInManager.PasswordSignInAsync("username", "Password123", false, shouldLockout: false);
- 用户已通过身份验证和授权。
基本上我的想法是为每个用户设置相同的密码,以便在应用程序中对他们进行身份验证并使用角色。
你怎么看?
因为身份是基于声明的。您不需要任何密码甚至任何用户对象来验证用户。所以在 Identity 中使用存储也是完全可选的。您只需要创建一些声明并根据这些声明授权您的用户。考虑这个简单的例子作为线索:
// imaging this action is called by proxy
public ActionResoult Login()
{
// this custom method extract username from header and check IP and more
var username=_myUserManager.GetUserName();
if(username!=null)
{
// optionally you have own user manager which returns roles from username
// no matter how you store users and roles
string[] roles=_myUserManager.GetUserRoles(username);
// user is valid, going to authenticate user for my App
var ident = new ClaimsIdentity(
new[]
{
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, username),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
// an optional claim you could omit this
new Claim(ClaimTypes.Name, username),
// populate assigned user's role form your DB
// and add each one as a claim
new Claim(ClaimTypes.Role, roles[0]),
new Claim(ClaimTypes.Role, roles[1]),
// and so on
},
DefaultAuthenticationTypes.ApplicationCookie);
// Identity is sign in user based on claim don't matter
// how you generated it
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
// auth is succeed, without needing any password just claim based
return RedirectToAction("MyAction");
}
// invalid user
ModelState.AddModelError("", "We could not authorize you :(");
return View();
}
现在我们无需任何密码即可授权我们的用户,因此我们也可以使用 Authorize
过滤器:
[Authorize]
public ActionResult Foo()
{
}
// since we injected user roles to Identity we could do this as well
[Authorize(Roles="admin")]
public ActionResult Foo()
{
// since we injected our authentication mechanism to Identity pipeline
// we have access current user principal by calling also
// HttpContext.User
}
注意:您的代理必须处理您的应用生成的 cookie 并将它们正确地传送给您的用户。由于您的应用程序基于 cookie。
您可以下载Token Based Authentication Sample from my Github repo and also read