I have a website thats build with VS 2012 Internet Application ( Simple membership) EF Code First
我有一个使用VS 2012 Internet Application(简单会员)EF Code First构建的网站
Updates
I would like to know how to extend HttpContext.User.IsInRole(role)
's functionality for a custom table -> User.IsInClient(client)
.
我想知道如何扩展HttpContext.User.IsInRole(角色)的自定义表 - > User.IsInClient(客户端)的功能。
4 个解决方案
#1
14
Here is the way I'd suggest to solve your issue:
以下是我建议您解决问题的方法:
Create your own interface which implements System.Security.Principal
, where you could place any methods you need:
创建自己的接口,实现System.Security.Principal,您可以在其中放置您需要的任何方法:
public interface ICustomPrincipal : IPrincipal
{
bool IsInClient(string client);
}
Implement this interface:
实现此接口:
public class CustomPrincipal : ICustomPrincipal
{
private readonly IPrincipal _principal;
public CustomPrincipal(IPrincipal principal) { _principal = principal; }
public IIdentity Identity { get { return _principal.Identity; } }
public bool IsInRole(string role) { return _principal.IsInRole(role); }
public bool IsInClient(string client)
{
return _principal.Identity.IsAuthenticated
&& GetClientsForUser(_principal.Identity.Name).Contains(client);
}
private IEnumerable<string> GetClientsForUser(string username)
{
using (var db = new YourContext())
{
var user = db.Users.SingleOrDefault(x => x.Name == username);
return user != null
? user.Clients.Select(x => x.Name).ToArray()
: new string[0];
}
}
}
In the Global.asax.cs assign your custom principal to the request user context (and optionally to the executing thread if you plan to use it later). I suggest to use Application_PostAuthenticateRequest
event not Application_AuthenticateRequest
for this assignment, otherwise your principal will be overridden (at least by ASP.NET MVC 4):
在Global.asax.cs中,将自定义主体分配给请求用户上下文(如果您打算稍后使用,则可选择将其分配给执行线程)。我建议使用Application_PostAuthenticateRequest事件而不是Application_AuthenticateRequest进行此赋值,否则将覆盖您的主体(至少通过ASP.NET MVC 4):
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
Context.User = Thread.CurrentPrincipal = new CustomPrincipal(User);
/*
* BTW: Here you could deserialize information you've stored earlier in the
* cookie of authenticated user. It would be helpful if you'd like to avoid
* redundant database queries, for some user-constant information, like roles
* or (in your case) user related clients. Just sample code:
*
* var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
* var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
* var cookieData = serializer.Deserialize<CookieData>(authCookie.UserData);
*
* Next, pass some deserialized data to your principal:
*
* Context.User = new CustomPrincipal(User, cookieData.clients);
*
* Obviously such data have to be available in the cookie. It should be stored
* there after you've successfully authenticated, e.g. in your logon action:
*
* if (Membership.ValidateUser(user, password))
* {
* var cookieData = new CookieData{...};
* var userData = serializer.Serialize(cookieData);
*
* var authTicket = new FormsAuthenticationTicket(
* 1,
* email,
* DateTime.Now,
* DateTime.Now.AddMinutes(15),
* false,
* userData);
*
* var authTicket = FormsAuthentication.Encrypt(authTicket);
* var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName,
authTicket);
* Response.Cookies.Add(authCookie);
* return RedirectToAction("Index", "Home");
* }
*/
}
Next, to be able to use the property User
from HttpContext
in the controller without casting it to ICustomPrincipal
each time, define base controller where you override the default User
property:
接下来,为了能够在控制器中使用来自HttpContext的属性,而不是每次都将其转换为ICustomPrincipal,定义基本控制器,您可以在其中覆盖默认的User属性:
public class BaseController : Controller
{
protected virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
Now, let other controllers inherit from it:
现在,让其他控制器继承它:
public class HomeController : BaseController
{
public ActionResult Index()
{
var x = User.IsInClient(name);
If you use Razor View Engine, and you'd like to be able to use your method in the very similar way on the views:
如果您使用Razor View Engine,并且希望能够以非常类似的方式在视图上使用您的方法:
@User.IsInClient(name)
you need to redefine WebViewPage
type:
您需要重新定义WebViewPage类型:
public abstract class BaseViewPage : WebViewPage
{
public virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
and tell Razor to reflect you changes, by modifying appropriate section of the Views\Web.config file:
并通过修改Views \ Web.config文件的相应部分告诉Razor反映您的更改:
<system.web.webPages.razor>
...
<pages pageBaseType="YourNamespace.BaseViewPage">
#2
0
Use Linq:
var Users = Membership.GetAllUsers();
//**Kinda Like Users.InCLients(userName).
var users = from x in Users
join y in db.Clinets on x.ProviderUserKey equals y.UserID
select x
//**Kinda Like Clients.InUsers(userName)
var clients = from x in db.Clinets
join y in Users on x.UserID equals y.ProviderUserKey
select x
#3
-1
try this way
试试这种方式
List<Clinets> AllClinets =entityObject.Clinets .ToList();
Foreach( var check in AllClinets)
{
if(check.UserTable.RoleTable.RoleName=="Rolename1")
{
//This users are Rolename1
}
else
{
//other.
}
}
#4
-2
Stored procedure would be better in this case.
在这种情况下,存储过程会更好。
#1
14
Here is the way I'd suggest to solve your issue:
以下是我建议您解决问题的方法:
Create your own interface which implements System.Security.Principal
, where you could place any methods you need:
创建自己的接口,实现System.Security.Principal,您可以在其中放置您需要的任何方法:
public interface ICustomPrincipal : IPrincipal
{
bool IsInClient(string client);
}
Implement this interface:
实现此接口:
public class CustomPrincipal : ICustomPrincipal
{
private readonly IPrincipal _principal;
public CustomPrincipal(IPrincipal principal) { _principal = principal; }
public IIdentity Identity { get { return _principal.Identity; } }
public bool IsInRole(string role) { return _principal.IsInRole(role); }
public bool IsInClient(string client)
{
return _principal.Identity.IsAuthenticated
&& GetClientsForUser(_principal.Identity.Name).Contains(client);
}
private IEnumerable<string> GetClientsForUser(string username)
{
using (var db = new YourContext())
{
var user = db.Users.SingleOrDefault(x => x.Name == username);
return user != null
? user.Clients.Select(x => x.Name).ToArray()
: new string[0];
}
}
}
In the Global.asax.cs assign your custom principal to the request user context (and optionally to the executing thread if you plan to use it later). I suggest to use Application_PostAuthenticateRequest
event not Application_AuthenticateRequest
for this assignment, otherwise your principal will be overridden (at least by ASP.NET MVC 4):
在Global.asax.cs中,将自定义主体分配给请求用户上下文(如果您打算稍后使用,则可选择将其分配给执行线程)。我建议使用Application_PostAuthenticateRequest事件而不是Application_AuthenticateRequest进行此赋值,否则将覆盖您的主体(至少通过ASP.NET MVC 4):
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
Context.User = Thread.CurrentPrincipal = new CustomPrincipal(User);
/*
* BTW: Here you could deserialize information you've stored earlier in the
* cookie of authenticated user. It would be helpful if you'd like to avoid
* redundant database queries, for some user-constant information, like roles
* or (in your case) user related clients. Just sample code:
*
* var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
* var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
* var cookieData = serializer.Deserialize<CookieData>(authCookie.UserData);
*
* Next, pass some deserialized data to your principal:
*
* Context.User = new CustomPrincipal(User, cookieData.clients);
*
* Obviously such data have to be available in the cookie. It should be stored
* there after you've successfully authenticated, e.g. in your logon action:
*
* if (Membership.ValidateUser(user, password))
* {
* var cookieData = new CookieData{...};
* var userData = serializer.Serialize(cookieData);
*
* var authTicket = new FormsAuthenticationTicket(
* 1,
* email,
* DateTime.Now,
* DateTime.Now.AddMinutes(15),
* false,
* userData);
*
* var authTicket = FormsAuthentication.Encrypt(authTicket);
* var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName,
authTicket);
* Response.Cookies.Add(authCookie);
* return RedirectToAction("Index", "Home");
* }
*/
}
Next, to be able to use the property User
from HttpContext
in the controller without casting it to ICustomPrincipal
each time, define base controller where you override the default User
property:
接下来,为了能够在控制器中使用来自HttpContext的属性,而不是每次都将其转换为ICustomPrincipal,定义基本控制器,您可以在其中覆盖默认的User属性:
public class BaseController : Controller
{
protected virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
Now, let other controllers inherit from it:
现在,让其他控制器继承它:
public class HomeController : BaseController
{
public ActionResult Index()
{
var x = User.IsInClient(name);
If you use Razor View Engine, and you'd like to be able to use your method in the very similar way on the views:
如果您使用Razor View Engine,并且希望能够以非常类似的方式在视图上使用您的方法:
@User.IsInClient(name)
you need to redefine WebViewPage
type:
您需要重新定义WebViewPage类型:
public abstract class BaseViewPage : WebViewPage
{
public virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new ICustomPrincipal User
{
get { return (ICustomPrincipal)base.User; }
}
}
and tell Razor to reflect you changes, by modifying appropriate section of the Views\Web.config file:
并通过修改Views \ Web.config文件的相应部分告诉Razor反映您的更改:
<system.web.webPages.razor>
...
<pages pageBaseType="YourNamespace.BaseViewPage">
#2
0
Use Linq:
var Users = Membership.GetAllUsers();
//**Kinda Like Users.InCLients(userName).
var users = from x in Users
join y in db.Clinets on x.ProviderUserKey equals y.UserID
select x
//**Kinda Like Clients.InUsers(userName)
var clients = from x in db.Clinets
join y in Users on x.UserID equals y.ProviderUserKey
select x
#3
-1
try this way
试试这种方式
List<Clinets> AllClinets =entityObject.Clinets .ToList();
Foreach( var check in AllClinets)
{
if(check.UserTable.RoleTable.RoleName=="Rolename1")
{
//This users are Rolename1
}
else
{
//other.
}
}
#4
-2
Stored procedure would be better in this case.
在这种情况下,存储过程会更好。