【问题标题】:How would I mimic User.IsInRole()我将如何模仿 User.IsInRole()
【发布时间】:2013-08-21 20:00:15
【问题描述】:

我有一个使用 VS 2012 Internet 应用程序(简单成员)EF Code First 构建的网站

更新

我想知道如何为自定义表格扩展 HttpContext.User.IsInRole(role) 的功能 -> User.IsInClient(client)

【问题讨论】:

  • bump.... 一种创建具有此功能的新类的方法?然后能够根据需要从 View 或 Controller 调用类.. ?
  • 你能解释清楚吗? Users.InRoles("Admin") 是什么?在哪里可以找到?它是在框架内还是您自定义的东西?也许您问的是HttpContext.User.IsInRole(role) 以及将此功能扩展到HttpContext.User.IsInClient(client) 的方法?
  • @JaroslawWaliszko 更新了问题,这样问更有意义。
  • 好的,我一会儿帮你。

标签: asp.net-mvc entity-framework simplemembership


【解决方案1】:

这是我建议的解决您问题的方法:

创建您自己的实现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");
     * }
     */         
}

接下来,为了能够在控制器中使用来自 HttpContext 的属性 User 而无需每次将其转换为 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 视图引擎,并且希望能够在视图上以非常相似的方式使用您的方法:

@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">

【讨论】:

  • @Don Thomas Boyle:WebViewPage 是来自System.Web.Mvc 命名空间的合法框架类。
  • 好的,所以我们只是覆盖已经存在但不可查看的 WebViewPage 类?
  • @Don Thomas Boyle:“不可见”是什么意思? WebViewPage 类型表示呈现使用 ASP.NET Razor 语法 (msdn.microsoft.com/en-us/library/gg402107(v=vs.108).aspx) 的视图所需的属性和方法。您将能够在视图上使用自定义类型的 User 对象,方法是覆盖此类并在 web.config 中指向 Razor 以使用它,而不是使用默认对象。
  • @Don Thomas Boyle:N/P。通过这样做和使用的简单性,您将获得智能感知支持,因为 Razor 会知道您的类型。所以不是@(((ICustomPrincipal)User).IsInClient(...)),而是:@User.IsInClient(...)
  • @Don Thomas Boyle:如果您想在自定义 IPrincipal 实现中避免冗余数据库查询,我已经添加了有关如何在 cookie 中存储/分配一些经过身份验证的用户数据的信息.
【解决方案2】:

使用 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 个表,难道不是 2 个连接吗? UsersClientsUserInCleints(拥有UserClient 的2 个ID)。但是membership.getallusers() 是neet。到目前为止我喜欢这个概念
  • @DonThomasBoyle 如果你有 UserInCleints 表,你可以加入它而不是用户表。
  • 是的,但这只会让我返回 ID,我想要与这些 ID 相关联的名称和其他信息。
  • @DonThomasBoyle 如果您需要所有数据,则可以使用连接,如示例所示。在这种情况下,您根本不需要 UserInCleints 表。或者您可以扩展您的 UserInCleints 表以获取更多数据,而不仅仅是 UserID。
【解决方案3】:

试试这个方法

List<Clinets> AllClinets =entityObject.Clinets .ToList();

Foreach( var check in AllClinets)
{
  if(check.UserTable.RoleTable.RoleName=="Rolename1")
   {
      //This users are Rolename1 
   }
  else
   {
   //other.
   }
}

【讨论】:

  • 我想你误解了,我正在尝试为 2 个非常独立的模型和方法重新创建 InRoles 的 InClients 方法,没有帮助器或类。跨度>
【解决方案4】:

在这种情况下,存储过程会更好。

【讨论】:

  • 对不起,这根本没有意义-1。
猜你喜欢
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-17
相关资源
最近更新 更多