Как бы я имитировал User.IsInRole()

У меня есть сайт, который строится с использованием интернет-приложения VS 2012 (простое членство) EF Code First

Обновления

Я хотел бы знать, как расширить функциональность HttpContext.User.IsInRole(role) для пользовательской таблицы → User.IsInClient(client).

4 ответа

Вот как я предлагаю решить вашу проблему:

Создайте свой собственный интерфейс, который реализует System.Security.Principal, где вы можете разместить любые методы, которые вам нужны:

public interface ICustomPrincipal : IPrincipal
{
 bool IsInClient(string client);
}

Внедрить этот интерфейс:

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];
 }
 }
}
</string>

В 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");
 * }
 */ 
}
</cookiedata>

Затем, чтобы иметь возможность использовать свойство User из HttpContext в контроллере, не меняя его на ICustomPrincipal каждый раз, определите базовый контроллер, где вы переопределите свойство User по умолчанию:

public class BaseController : Controller
{
 protected virtual new ICustomPrincipal User
 {
 get { return (ICustomPrincipal)base.User; }
 }
}

Теперь позвольте другим контроллерам наследовать от него:

public class HomeController : BaseController
{
 public ActionResult Index()
 {
 var x = User.IsInClient(name);

Если вы используете Razor View Engine, и вы хотели бы иметь возможность использовать свой метод очень похожим образом:

@User.IsInClient(name)

вам нужно переопределить тип 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; }
 }
}
</tmodel></tmodel>

и скажите Razor, чтобы отразить ваши изменения, изменив соответствующий раздел файла Views\Web.config:

<system.web.webpages.razor>
 ...
 </system.web.webpages.razor>


Использовать 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


попробуйте этот путь

List<clinets> AllClinets =entityObject.Clinets .ToList();
Foreach( var check in AllClinets)
{
 if(check.UserTable.RoleTable.RoleName=="Rolename1")
 {
 //This users are Rolename1 
 }
 else
 {
 //other.
 }
}
</clinets>


Сохраненная процедура была бы лучше в этом случае.

licensed under cc by-sa 3.0 with attribution.