How would I mimic User.IsInRole()

后端 未结 4 1584
被撕碎了的回忆
被撕碎了的回忆 2020-12-30 13:38

I have a website thats build with VS 2012 Internet Application ( Simple membership) EF Code First

Updates

I would like

相关标签:
4条回答
  • 2020-12-30 14:31

    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
    
    0 讨论(0)
  • 2020-12-30 14:41

    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.
       }
    }
    
    0 讨论(0)
  • 2020-12-30 14:42

    Stored procedure would be better in this case.

    0 讨论(0)
  • 2020-12-30 14:43

    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:

    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):

    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:

    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:

    @User.IsInClient(name)
    

    you need to redefine WebViewPage type:

    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:

    <system.web.webPages.razor>
        ...
        <pages pageBaseType="YourNamespace.BaseViewPage">
    
    0 讨论(0)
提交回复
热议问题