如何允许用户仅在目录中编辑其详细信息

时间:2014-01-24 09:09:07

标签: asp.net-mvc asp.net-mvc-5

我开始使用MVC 5教程并实现角色和用户,然后是链接:

http://typecastexception.com/post/2013/11/11/Extending-Identity-Accounts-and-Implementing-Role-Based-Authentication-in-ASPNET-MVC-5.aspx

通过基于角色的身份验证,我现在拥有一个可以创建用户的管理员以及目录控制器下列出的公司目录。只有当用户使用管理员设置的用户名和密码登录时,该用户才会被重定向到他们所代表的公司页面进行编辑,而不是自由控制编辑其他人的公司。

我该怎么做呢?

这是我的AccountController:

 [Authorize]
public class AccountController : Controller
{
    public AccountController()
        : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
    {
    }


    public AccountController(UserManager<ApplicationUser> userManager)
    {
        UserManager = userManager;
    }


    public UserManager<ApplicationUser> UserManager { get; private set; }


    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }


    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindAsync(model.UserName, model.Password);
            if (user != null)
            {
                await SignInAsync(user, model.RememberMe);

            }

            //if (User.Identity.AuthenticationType == "CanEdit" )
            //{
            //    return RedirectToAction()
            //}
            else
            {
                ModelState.AddModelError("", "Invalid username or password.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }


    [Authorize(Roles = "Admin")]
    public ActionResult Register()
    {
        return View();
    }


    [HttpPost]
    [Authorize(Roles = "Admin")]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = model.GetUser();
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction("Index", "Account");
            }

        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }


    [Authorize(Roles = "Admin")]
    public ActionResult Manage(ManageMessageId? message)
    {
        ViewBag.StatusMessage =
            message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
            : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
            : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
            : message == ManageMessageId.Error ? "An error has occurred."
            : "";
        ViewBag.HasLocalPassword = HasPassword();
        ViewBag.ReturnUrl = Url.Action("Manage");
        return View();
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "Admin")]
    public async Task<ActionResult> Manage(ManageUserViewModel model)
    {
        bool hasPassword = HasPassword();
        ViewBag.HasLocalPassword = hasPassword;
        ViewBag.ReturnUrl = Url.Action("Manage");
        if (hasPassword)
        {
            if (ModelState.IsValid)
            {
                IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
                if (result.Succeeded)
                {
                    return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
                }
                else
                {
                    AddErrors(result);
                }
            }
        }
        else
        {
            // User does not have a password so remove any validation errors caused by a missing OldPassword field
            ModelState state = ModelState["OldPassword"];
            if (state != null)
            {
                state.Errors.Clear();
            }

            if (ModelState.IsValid)
            {
                IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
                if (result.Succeeded)
                {
                    return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
                }
                else
                {
                    AddErrors(result);
                }
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Index", "Home");
    }


    protected override void Dispose(bool disposing)
    {
        if (disposing && UserManager != null)
        {
            UserManager.Dispose();
            UserManager = null;
        }
        base.Dispose(disposing);
    }


    [Authorize(Roles = "Admin")]
    public ActionResult Index()
    {
        var Db = new ApplicationDbContext();
        var users = Db.Users;
        var model = new List<EditUserViewModel>();
        foreach (var user in users)
        {
            var u = new EditUserViewModel(user);
            model.Add(u);
        }
        return View(model);
    }


    [Authorize(Roles = "Admin")]
    public ActionResult Edit(string id, ManageMessageId? Message = null)
    {
        var Db = new ApplicationDbContext();
        var user = Db.Users.First(u => u.UserName ==id);
        var model = new EditUserViewModel(user);
        ViewBag.MessageId = Message;
        return View(model);
    }


    [HttpPost]
    [Authorize(Roles = "Admin")]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(EditUserViewModel model)
    {
        if (ModelState.IsValid)
        {
            var Db = new ApplicationDbContext();
            var user = Db.Users.First(u => u.UserName == model.UserName);
            user.FirstName = model.FirstName;
            user.LastName = model.LastName;
            user.Email = model.Email;
            Db.Entry(user).State = System.Data.Entity.EntityState.Modified;
            await Db.SaveChangesAsync();
            return RedirectToAction("Index");
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

    [Authorize(Roles = "Admin")]
    public ActionResult Delete(string id = null)
    {
        var Db = new ApplicationDbContext();
        var user = Db.Users.First(u => u.UserName == id);
        var model = new EditUserViewModel(user);
        if (user == null)
        {
            return HttpNotFound();
        }
        return View(model);
    }


    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "Admin")]
    public ActionResult DeleteConfirmed(string id)
    {
        var Db = new ApplicationDbContext();
        var user = Db.Users.First(u => u.UserName == id);
        Db.Users.Remove(user);
        Db.SaveChanges();
        return RedirectToAction("Index");
    }


    [Authorize(Roles = "Admin")]
    public ActionResult UserRoles(string id)
    {
        var Db = new ApplicationDbContext();
        var user = Db.Users.First(u => u.UserName == id);
        var model = new SelectUserRolesViewModel(user);
        return View(model);
    }


    [HttpPost]
    [Authorize(Roles = "Admin")]
    [ValidateAntiForgeryToken]
    public ActionResult UserRoles(SelectUserRolesViewModel model)
    {
        if (ModelState.IsValid)
        {
            var idManager = new IdentityManager();
            var Db = new ApplicationDbContext();
            var user = Db.Users.First(u => u.UserName == model.UserName);
            idManager.ClearUserRoles(user.Id);
            foreach (var role in model.Roles)
            {
                if (role.Selected)
                {
                    idManager.AddUserToRole(user.Id, role.RoleName);
                }
            }
            return RedirectToAction("index");
        }
        return View();
    }


    #region Helpers

    private IAuthenticationManager AuthenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }


    private async Task SignInAsync(ApplicationUser user, bool isPersistent)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
        AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }


    private void AddErrors(IdentityResult result)
    {
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError("", error);
        }
    }


    private bool HasPassword()
    {
        var user = UserManager.FindById(User.Identity.GetUserId());
        if (user != null)
        {
            return user.PasswordHash != null;
        }
        return false;
    }


    public enum ManageMessageId
    {
        ChangePasswordSuccess,
        SetPasswordSuccess,
        RemoveLoginSuccess,
        Error
    }


    private ActionResult RedirectToLocal(string returnUrl)
    {
        if (Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }
        else
        {
            return RedirectToAction("Index", "Home");
        }
    }

    #endregion
}

修改视图

Catalog Controller edit view:`@model Catalog.Models.Partner

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>


@using (Html.BeginForm("Edit", "Catalog", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Company, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Company, new { @class = "form-control", autocomplete = "off" })
                @Html.ValidationMessageFor(model => model.Company)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Description, new { @class = "form-control", autocomplete = "off" })
                @Html.ValidationMessageFor(model => model.Description)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Details, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.Details, new { @class = "form-control", rows = 10 })
                @Html.ValidationMessageFor(model => model.Details)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.InCharge, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.InCharge, new { @class = "form-control", autocomplete = "off" })
                @Html.ValidationMessageFor(model => model.InCharge)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Email, new { @class = "form-control", autocomplete = "off" })
                @Html.ValidationMessageFor(model => model.Email)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Logo, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <input type="file" name="file" />
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<hr />
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

`

2 个答案:

答案 0 :(得分:2)

在获取数据库上下文时,添加一个Where()子句,它只会获取当前用户所属的信息。如果将其添加为命名空间using Microsoft.AspNet.Identity;,则可以使用User.Identity.GetUserId()返回当前用户的ID,并在Where()子句中使用该ID仅查看用户/合作伙伴可以看到的内容。

答案 1 :(得分:2)

尽管有问题的日期,我会在这里留下我的答案,因为当你开发一个应用程序时,这个问题是相关的,并且需要让只有登录的用户看到,编辑或删除(或任何其他动作)它自己的记录。

使用实体框架和ASP.NET标识显示示例。

首先,您需要将对象模型与用户链接起来。这由IdentityUser表示。请注意,我们使用的是IdentityUser类,因为我们使用的是ASP.NET Identity,否则我们可以使用ClaimsIdentity

public class UserObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IdentityUser User { get; set; }
}

在您的Context上保存UserObject之后,将创建引用Id IdentityUser属性的字段(此类的表的默认名称为AspNetUsers)以及UserObject表。

然后,为了获得当前用户,请致电HttpContext.GetOwinContext().Get<UserManager>()以获取UserManager,然后拨打UserManager.FindById(User.Idendity.GetUserId())。只需记住在插入新对象时获取与Owin Context相关联的IdentityDbContext,否则将抛出异常。

public ActionResult Create(UserObjectViewModel uoViewModel)
{
    UserObject uo = new UserObject();

    // create the UserObject using the properties from the UserObjectViewModel
    ...

    // get the User Manager
    UserManager userManager = HttpContext.GetOwinContext().Get<UserManager>();

    // assign the current User
    uo.User = userManager.FindById(User.Identity.GetUserId())

    ...
}

从现在开始,您可以致电User.Identity.GetUserId()获取当前用户ID,并将其与您的查询参数一起发送:

public ActionResult Get()
{
    string currentUserId = User.Identity.GetUserId();

    yourDbContext.Where(uo => uo.User.Id == currentUserId);

    ...
}