Как бы я подражал 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];
        }
    }
}

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

Далее, чтобы иметь возможность использовать собственность 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; }
    }
}

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

<system.web.webPages.razor>
    ...
    <pages pageBaseType="YourNamespace.BaseViewPage">

Используйте 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.
   }
}

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

Другие вопросы по тегам