在前一篇贴文中,已探索过如何在MVC5中自定ASP.NET Identity,接下来要来试试在MVC5中如何运用 ASP.NET Identity来设定一个以 "角色"为基础的授权机制。为了方便起见,简化了这个认证机制的内容,同时假设这是一个公司内部使用的应用程序,所以拿掉了"注册"的功能,所有的使用账 号管理都必须透过某一管理权限(Admin)的使用者来进行,也就是说只有具备有 Admin 角色的使用者可以执行”账户管理"的功能。
贴文内容:
建立MVC5新项目
修改相关 Mdels
扩展Identity Management Mdel 
 加入新字段
 建立Helper Class
扩展Accunt Management ViewMdels (AccuntViewMdels.cs)
 在RegisterViewMdel加入新字段 及 GetUser methd
 新增 EditUserViewMdel、SelectUserRlesViewMdel、SelectRleEditrViewMdel
修改相关 Cntrllers
修改AccuntCntrller 中 Register Methd 加入 Authrize attribute
加入 Index Methd (ActinResult)
加入 Edit Methd (ActinResult)
加入 Delete Methd (ActinResult)
加入 UserRles Methd (ActinResult)
修改相关 Views
修改Register.cshtml View 
新增Edit、Delete、Index 等方法的Views
新增UserRles.cshtml View 并 新增程序代码
新增 SelectRleEditrViewMdel.cshtml 在 Shared/EditrTemplates目录下
在主页面上新增”账号管理" 功能按钮
移除主页面上的注册功能
启动 Migratin功能
在Seed()方法中加入建立测试数据的程序代码
更新数据库
执行结果
 
建立MVC5新项目
 


 

修改相关 Models
 
1. 扩展Identity Management Model (IdentityModels.cs)
 
加入新字段:为使用者数据多加三个属性字段,分别是FirstName、LastName、Email。
 

 
建立Helper Class:利用Asp.Net Identity API建立一个 Identity Management Helper class: IdentityManager class,包含有建立角色、建立使用者...等功能。
 

 
IdentityModels.cs 完整程序

01.using Microsoft.AspNet.Identity;
02.using Microsoft.AspNet.Identity.EntityFramework;
03.using System.Collections.Generic;
04.using System.ComponentModel.DataAnnotations;
05. 
06.namespace RoleBaseProject.Models
07.{
08.// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
09.public class ApplicationUser : IdentityUser
10.{
11.[Required]
12.public string FirstName { get; set; }
13. 
14.[Required]
15.public string LastName { get; set; }
16.[Required]
17.public string Email { get; set; }
18.}
19. 
20.public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
21.{
22.public ApplicationDbContext()
23.: base("DefaultConnection")
24.{
25.}
26.}
27. 
28.public class IdentityManager
29.{
30.// 判断角色是否已在存在
31.public bool RoleExists(string name)
32.{
33.var rm = new RoleManager<IdentityRole>(
34.new RoleStore<IdentityRole>(new ApplicationDbContext()));
35.return rm.RoleExists(name);
36.}
37.// 新增角色
38.public bool CreateRole(string name)
39.{
40.var rm = new RoleManager<IdentityRole>(
41.new RoleStore<IdentityRole>(new ApplicationDbContext()));
42.var idResult = rm.Create(new IdentityRole(name));
43.return idResult.Succeeded;
44.}
45.// 新增角色
46.public bool CreateUser(ApplicationUser user, string pass<a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>)
47.{
48.var um = new UserManager<ApplicationUser>(
49.new UserStore<ApplicationUser>(new ApplicationDbContext()));
50.var idResult = um.Create(user, pass<a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>);
51.return idResult.Succeeded;
52.}
53.// 将使用者加入角色中
54.public bool AddUserToRole(string userId, string roleName)
55.{
56.var um = new UserManager<ApplicationUser>(
57.new UserStore<ApplicationUser>(new ApplicationDbContext()));
58.var idResult = um.AddToRole(userId, roleName);
59.return idResult.Succeeded;
60.}
61.// 清除使用者的角色设定
62.public void ClearUserRoles(string userId)
63.{
64.var um = new UserManager<ApplicationUser>(
65.new UserStore<ApplicationUser>(new ApplicationDbContext()));
66.var user = um.FindById(userId);
67.var currentRoles = new List<IdentityUserRole>();
68.currentRoles.AddRange(user.Roles);
69.foreach(var role in currentRoles)
70.{
71.um.RemoveFromRole(userId, role.Role.Name);
72.}
73.}
74.}
75.}
2. 扩展Account Management ViewModels (AccountViewModels.cs)
 
在RegisterViewModel加入新字段 及 GetUser method
 

 
 
针对要新增的"账号管理"功能新增三个ViewModel,分别是: EditUserViewModel、SelectUserRolesViewModel、SelectRoleEditorViewModel
 
AccountViewModels.cs 完整程序
001.using Microsoft.AspNet.Identity.EntityFramework;
002.using System.Collections.Generic;
003.using System.ComponentModel.DataAnnotations;
004. 
005.namespace RoleBaseProject.Models
006.{
007.public class ExternalLoginConfirmationViewModel
008.{
009.[Required]
010.[Display(Name = "使用者名称")]
011.public string UserName { get; set; }
012.}
013. 
014.public class ManageUserViewModel
015.{
016.[Required]
017.[DataType(DataType.Password)]
018.[Display(Name = "目前密码")]
019.public string OldPassword { get; set; }
020. 
021.[Required]
022.[StringLength(100, ErrorMessage = "{0} 的长度至少必须为 {2} 个字符。", MinimumLength = 6)]
023.[DataType(DataType.Password)]
024.[Display(Name = "新密码")]
025.public string NewPassword { get; set; }
026. 
027.[DataType(DataType.Password)]
028.[Display(Name = "确认新密码")]
029.[Compare("NewPassword", ErrorMessage = "新密码与确认密码不相符。")]
030.public string ConfirmPassword { get; set; }
031.}
032. 
033.public class LoginViewModel
034.{
035.[Required]
036.[Display(Name = "使用者名称")]
037.public string UserName { get; set; }
038. 
039.[Required]
040.[DataType(DataType.Password)]
041.[Display(Name = "密码")]
042.public string Password { get; set; }
043. 
044.[Display(Name = "记住我?")]
045.public bool RememberMe { get; set; }
046.}
047. 
048.public class RegisterViewModel
049.{
050.[Required]
051.[Display(Name = "使用者名称")]
052.public string UserName { get; set; }
053. 
054.[Required]
055.[StringLength(100, ErrorMessage = "{0} 的长度至少必须为 {2} 个字符。", MinimumLength = 6)]
056.[DataType(DataType.Password)]
057.[Display(Name = "密码")]
058.public string Password { get; set; }
059. 
060.[DataType(DataType.Password)]
061.[Display(Name = "确认密码")]
062.[Compare("Password", ErrorMessage = "密码和确认密码不相符。")]
063.public string ConfirmPassword { get; set; }
064. 
065.[Required]
066.[Display(Name = "First Name")]
067.public string FirstName { get; set; }
068. 
069.[Required]
070.[Display(Name = "Last Name")]
071.public string LastName { get; set; }
072. 
073.[Required]
074.[Display(Name = "电子邮件信箱")]
075.public string Email { get; set; }
076. 
077.public ApplicationUser GetUser()
078.{
079.var user = new ApplicationUser()
080.{
081.UserName = this.UserName,
082.FirstName = this.FirstName,
083.LastName = this.LastName,
084.Email = this.Email,
085.};
086.return user;
087.}
088.}
089. 
090.public class EditUserViewModel
091.{
092.public EditUserViewModel() { }
093. 
094.// Allow Initialization with an instance of ApplicationUser:
095.public EditUserViewModel(ApplicationUser user)
096.{
097.this.UserName = user.UserName;
098.this.FirstName = user.FirstName;
099.this.LastName = user.LastName;
100.this.Email = user.Email;
101.}
102. 
103.[Required]
104.[Display(Name = "使用者账号")]
105.public string UserName { get; set; }
106. 
107.[Required]
108.[Display(Name = "名")]
109.public string FirstName { get; set; }
110. 
111.[Required]
112.[Display(Name = "姓")]
113.public string LastName { get; set; }
114. 
115.[Required]
116.[Display(Name = "电子邮件信箱")]
117.public string Email { get; set; }
118.}
119. 
120.public class SelectUserRolesViewModel
121.{
122.public SelectUserRolesViewModel()
123.{
124.this.Roles = new List<SelectRoleEditorViewModel>();
125.}
126. 
127.// Enable initialization with an instance of ApplicationUser:
128.public SelectUserRolesViewModel(ApplicationUser user)
129.: this()
130.{
131.this.UserName = user.UserName;
132.this.FirstName = user.FirstName;
133.this.LastName = user.LastName;
134. 
135.var Db = new ApplicationDbContext();
136. 
137.// Add all available roles to the list of EditorViewModels:
138.var allRoles = Db.Roles;
139.foreach (var role in allRoles)
140.{
141.// An EditorViewModel will be used by Editor Template:
142.var rvm = new SelectRoleEditorViewModel(role);
143.this.Roles.Add(rvm);
144.}
145. 
146.// Set the Selected property to true for those roles for
147.// which the current user is a member:
148.foreach (var userRole in user.Roles)
149.{
150.var checkUserRole =
151.this.Roles.Find(r => r.RoleName == userRole.Role.Name);
152.checkUserRole.Selected = true;
153.}
154.}
155. 
156.public string UserName { get; set; }
157.public string FirstName { get; set; }
158.public string LastName { get; set; }
159.public List<SelectRoleEditorViewModel> Roles { get; set; }
160.}
161. 
162.// Used to display a single role with a checkbox, within a list structure:
163.public class SelectRoleEditorViewModel
164.{
165.public SelectRoleEditorViewModel() { }
166.public SelectRoleEditorViewModel(IdentityRole role)
167.{
168.this.RoleName = role.Name;
169.}
170. 
171.public bool Selected { get; set; }
172. 
173.[Required]
174.public string RoleName { get; set; }
175.}
176. 
177.}
修改相关 Controllers
 
修改AccountController 中 Register Method 加入 Authorize attribute
 

 
 

必须具有Admin 角色者才能执行。

 
加入 Index Method (ActionResult)
01.[Authorize(Roles = "Admin")]
02.public ActionResult Index()
03.{
04.var Db = new ApplicationDbContext();
05.var users = Db.Users;
06.var model = new List<EditUserViewModel>();
07.foreach(var user in users)
08.{
09.var u = new EditUserViewModel(user);
10.model.Add(u);
11.}
12.return View(model);
13.}

加入 Edit Method (ActionResult)

01.//
02.// GEG: /Account/Edit
03.[Authorize(Roles = "Admin")]
04.public ActionResult Edit(string id , ManageMessageId? Message = null)
05.{
06.var Db = new ApplicationDbContext();
07.var user = Db.Users.First(u => u.UserName == id);
08.var model = new EditUserViewModel(user);
09.ViewBag.MessageId = Message;
10.return View(model);
11.}
12.//
13.// POST: /Account/Edit
14.[HttpPost]
15.[Authorize(Roles = "Admin")]
16.[ValidateAntiForgeryToken]
17.public async Task<ActionResult> Edit(EditUserViewModel model)
18.{
19.if (ModelState.IsValid)
20.{
21.var Db = new ApplicationDbContext();
22.var user = Db.Users.First(u => u.UserName == model.UserName);
23.user.FirstName = model.FirstName;
24.user.LastName = model.LastName;
25.user.Email = model.Email;
26.Db.Entry(user).State = System.Data.Entity.EntityState.Modified;
27.await Db.SaveChangesAsync();
28.return RedirectToAction("Index");
29.}
30.return View(model);
31.}

加入 Delete Method (ActionResult)

01.//
02.// GEG: /Account/Delete
03.[Authorize(Roles="Admin")]
04.public ActionResult Delete(string id = null)
05.{
06.var Db = new ApplicationDbContext();
07.var user = Db.Users.First(u => u.UserName == id);
08.var model = new EditUserViewModel(user);
09.return View(model);
10.}
11.//
12.// POST: /Account/Delete
13.[HttpPost, ActionName("Delete")]
14.[Authorize(Roles = "Admin")]
15.[ValidateAntiForgeryToken]
16.public ActionResult DeleteConfirmed(string id)
17.{
18.var Db = new ApplicationDbContext();
19.var user = Db.Users.First(u => u.UserName == id);
20.Db.Users.Remove(user);
21.Db.SaveChanges();
22.return RedirectToAction("Index");
23.}

加入 UserRoles Method (ActionResult)

01.//
02.// GEG: /Account/UserRoles
03.[Authorize(Roles = "Admin")]
04.public ActionResult UserRoles(string id)
05.{
06.var Db = new ApplicationDbContext();
07.var user = Db.Users.First(u => u.UserName == id);
08.var model = new SelectUserRolesViewModel(user);
09.return View(model);
10.}
11. 
12.//
13.// POST: /Account/UserRoles
14.[HttpPost]
15.[Authorize(Roles = "Admin")]
16.[ValidateAntiForgeryToken]
17.public ActionResult UserRoles(SelectUserRolesViewModel model)
18.{
19.if (ModelState.IsValid)
20.{
21.var idManager = new IdentityManager();
22.var Db = new ApplicationDbContext();
23.var user = Db.Users.First(u => u.UserName == model.UserName);
24.idManager.ClearUserRoles(user.Id);
25.foreach (var role in model.Roles)
26.{
27.if (role.Selected)
28.{
29.idManager.AddUserToRole(user.Id, role.RoleName);
30.}
31.}
32.return RedirectToAction("index");
33.}
34.return View();
35.}

AccountController.cs 完整程序

001.using System;
002.using System.Collections.Generic;
003.using System.Linq;
004.using System.Security.Claims;
005.using System.Threading.Tasks;
006.using System.Web;
007.using System.Web.Mvc;
008.using Microsoft.AspNet.Identity;
009.using Microsoft.AspNet.Identity.EntityFramework;
010.using Microsoft.Owin.Security;
011.using RoleBaseProject.Models;
012. 
013.namespace RoleBaseProject.Controllers
014.{
015.[Authorize]
016.public class AccountController : Controller
017.{
018.public AccountController()
019.: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
020.{
021.}
022. 
023.public AccountController(UserManager<ApplicationUser> userManager)
024.{
025.UserManager = userManager;
026.}
027. 
028.public UserManager<ApplicationUser> UserManager { get; private set; }
029. 
030.//
031.// GET: /Account/Login
032.[AllowAnonymous]
033.public ActionResult Login(string returnUrl)
034.{
035.ViewBag.ReturnUrl = returnUrl;
036.return View();
037.}
038. 
039.//
040.// POST: /Account/Login
041.[HttpPost]
042.[AllowAnonymous]
043.[ValidateAntiForgeryToken]
044.public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
045.{
046.if (ModelState.IsValid)
047.{
048.var user = await UserManager.FindAsync(model.UserName, model.Password);
049.if (user != null)
050.{
051.await SignInAsync(user, model.RememberMe);
052.return RedirectToLocal(returnUrl);
053.}
054.else
055.{
056.ModelState.AddModelError("", "Invalid username or password.");
057.}
058.}
059. 
060.// 如果执行到这里,发生某项失败,则重新显示窗体
061.return View(model);
062.}
063. 
064.//
065.// GET: /Account/Register
066.[Authorize(Roles="Admin")]
067.public ActionResult Register()
068.{
069.return View();
070.}
071. 
072.//
073.// POST: /Account/Register
074.[HttpPost]
075.[Authorize(Roles = "Admin")]
076.[ValidateAntiForgeryToken]
077.public async Task<ActionResult> Register(RegisterViewModel model)
078.{
079.if (ModelState.IsValid)
080.{
081.var user = new ApplicationUser() {
082.UserName = model.UserName,
083.FirstName = model.FirstName,
084.LastName = model.LastName,
085.Email = model.Email,
086.};
087.var result = await UserManager.CreateAsync(user, model.Password);
088.if (result.Succeeded)
089.{
090.await SignInAsync(user, isPersistent: false);
091.return RedirectToAction("Index", "Home");
092.}
093.else
094.{
095.AddErrors(result);
096.}
097.}
098. 
099.// 如果执行到这里,发生某项失败,则重新显示窗体
100.return View(model);
101.}
102. 
103.//
104.// GEG: /Account/Index
105.[Authorize(Roles = "Admin")]
106.public ActionResult Index()
107.{
108.var Db = new ApplicationDbContext();
109.var users = Db.Users;
110.var model = new List<EditUserViewModel>();
111.foreach(var user in users)
112.{
113.var u = new EditUserViewModel(user);
114.model.Add(u);
115.}
116.return View(model);
117.}
118. 
119.//
120.// GEG: /Account/Edit
121.[Authorize(Roles = "Admin")]
122.public ActionResult Edit(string id , ManageMessageId? Message = null)
123.{
124.var Db = new ApplicationDbContext();
125.var user = Db.Users.First(u => u.UserName == id);
126.var model = new EditUserViewModel(user);
127.ViewBag.MessageId = Message;
128.return View(model);
129.}
130.//
131.// POST: /Account/Edit
132.[HttpPost]
133.[Authorize(Roles = "Admin")]
134.[ValidateAntiForgeryToken]
135.public async Task<ActionResult> Edit(EditUserViewModel model)
136.{
137.if (ModelState.IsValid)
138.{
139.var Db = new ApplicationDbContext();
140.var user = Db.Users.First(u => u.UserName == model.UserName);
141.user.FirstName = model.FirstName;
142.user.LastName = model.LastName;
143.user.Email = model.Email;
144.Db.Entry(user).State = System.Data.Entity.EntityState.Modified;
145.await Db.SaveChangesAsync();
146.return RedirectToAction("Index");
147.}
148.return View(model);
149.}
150. 
151.//
152.// GEG: /Account/Delete
153.[Authorize(Roles="Admin")]
154.public ActionResult Delete(string id = null)
155.{
156.var Db = new ApplicationDbContext();
157.var user = Db.Users.First(u => u.UserName == id);
158.var model = new EditUserViewModel(user);
159.return View(model);
160.}
161.//
162.// POST: /Account/Delete
163.[HttpPost, ActionName("Delete")]
164.[Authorize(Roles = "Admin")]
165.[ValidateAntiForgeryToken]
166.public ActionResult DeleteConfirmed(string id)
167.{
168.var Db = new ApplicationDbContext();
169.var user = Db.Users.First(u => u.UserName == id);
170.Db.Users.Remove(user);
171.Db.SaveChanges();
172.return RedirectToAction("Index");
173.}
174.//
175.// GEG: /Account/UserRoles
176.[Authorize(Roles = "Admin")]
177.public ActionResult UserRoles(string id)
178.{
179.var Db = new ApplicationDbContext();
180.var user = Db.Users.First(u => u.UserName == id);
181.var model = new SelectUserRolesViewModel(user);
182.return View(model);
183.}
184. 
185.//
186.// POST: /Account/UserRoles
187.[HttpPost]
188.[Authorize(Roles = "Admin")]
189.[ValidateAntiForgeryToken]
190.public ActionResult UserRoles(SelectUserRolesViewModel model)
191.{
192.if (ModelState.IsValid)
193.{
194.var idManager = new IdentityManager();
195.var Db = new ApplicationDbContext();
196.var user = Db.Users.First(u => u.UserName == model.UserName);
197.idManager.ClearUserRoles(user.Id);
198.foreach (var role in model.Roles)
199.{
200.if (role.Selected)
201.{
202.idManager.AddUserToRole(user.Id, role.RoleName);
203.}
204.}
205.return RedirectToAction("index");
206.}
207.return View();
208.}
209. 
210.//
211.// POST: /Account/Disassociate
212.[HttpPost]
213.[ValidateAntiForgeryToken]
214.public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
215.{
216.ManageMessageId? message = null;
217.IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
218.if (result.Succeeded)
219.{
220.message = ManageMessageId.RemoveLoginSuccess;
221.}
222.else
223.{
224.message = ManageMessageId.Error;
225.}
226.return RedirectToAction("Manage", new { Message = message });
227.}
228. 
229.//
230.// GET: /Account/Manage
231.public ActionResult Manage(ManageMessageId? message)
232.{
233.ViewBag.StatusMessage =
234.message == ManageMessageId.ChangePasswordSuccess ? "您的密码已变更。"
235.: message == ManageMessageId.SetPasswordSuccess ? "已设定您的密码。"
236.: message == ManageMessageId.RemoveLoginSuccess ? "已移除外部登入。"
237.: message == ManageMessageId.Error ? "发生错误。"
238.: "";
239.ViewBag.HasLocalPassword = HasPassword();
240.ViewBag.ReturnUrl = Url.Action("Manage");
241.return View();
242.}
243. 
244.//
245.// POST: /Account/Manage
246.[HttpPost]
247.[ValidateAntiForgeryToken]
248.public async Task<ActionResult> Manage(ManageUserViewModel model)
249.{
250.bool hasPassword = HasPassword();
251.ViewBag.HasLocalPassword = hasPassword;
252.ViewBag.ReturnUrl = Url.Action("Manage");
253.if (hasPassword)
254.{
255.if (ModelState.IsValid)
256.{
257.IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
258.if (result.Succeeded)
259.{
260.return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
261.}
262.else
263.{
264.AddErrors(result);
265.}
266.}
267.}
268.else
269.{
270.// User does not have a password so remove any validation errors caused by a missing OldPassword field
271.ModelState state = ModelState["OldPassword"];
272.if (state != null)
273.{
274.state.Errors.Clear();
275.}
276. 
277.if (ModelState.IsValid)
278.{
279.IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
280.if (result.Succeeded)
281.{
282.return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
283.}
284.else
285.{
286.AddErrors(result);
287.}
288.}
289.}
290. 
291.// 如果执行到这里,发生某项失败,则重新显示窗体
292.return View(model);
293.}
294. 
295.//
296.// POST: /Account/ExternalLogin
297.[HttpPost]
298.[AllowAnonymous]
299.[ValidateAntiForgeryToken]
300.public ActionResult ExternalLogin(string provider, string returnUrl)
301.{
302.// 要求重新导向至外部登入提供者
303.return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
304.}
305. 
306.//
307.// GET: /Account/ExternalLoginCallback
308.[AllowAnonymous]
309.public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
310.{
311.var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
312.if (loginInfo == null)
313.{
314.return RedirectToAction("Login");
315.}
316. 
317.// Sign in the user with this external login provider if the user already has a login
318.var user = await UserManager.FindAsync(loginInfo.Login);
319.if (user != null)
320.{
321.await SignInAsync(user, isPersistent: false);
322.return RedirectToLocal(returnUrl);
323.}
324.else
325.{
326.// If the user does not have an account, then prompt the user to create an account
327.ViewBag.ReturnUrl = returnUrl;
328.ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
329.return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
330.}
331.}
332. 
333.//
334.// POST: /Account/LinkLogin
335.[HttpPost]
336.[ValidateAntiForgeryToken]
337.public ActionResult LinkLogin(string provider)
338.{
339.// Request a redirect to the external login provider to link a login for the current user
340.return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
341.}
342. 
343.//
344.// GET: /Account/LinkLoginCallback
345.public async Task<ActionResult> LinkLoginCallback()
346.{
347.var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
348.if (loginInfo == null)
349.{
350.return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
351.}
352.var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
353.if (result.Succeeded)
354.{
355.return RedirectToAction("Manage");
356.}
357.return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
358.}
359. 
360.//
361.// POST: /Account/ExternalLoginConfirmation
362.[HttpPost]
363.[AllowAnonymous]
364.[ValidateAntiForgeryToken]
365.public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
366.{
367.if (User.Identity.IsAuthenticated)
368.{
369.return RedirectToAction("Manage");
370.}
371. 
372.if (ModelState.IsValid)
373.{
374.// 从外部登入提供者处取得使用者信息
375.var info = await AuthenticationManager.GetExternalLoginInfoAsync();
376.if (info == null)
377.{
378.return View("ExternalLoginFailure");
379.}
380.var user = new ApplicationUser() { UserName = model.UserName };
381.var result = await UserManager.CreateAsync(user);
382.if (result.Succeeded)
383.{
384.result = await UserManager.AddLoginAsync(user.Id, info.Login);
385.if (result.Succeeded)
386.{
387.await SignInAsync(user, isPersistent: false);
388.return RedirectToLocal(returnUrl);
389.}
390.}
391.AddErrors(result);
392.}
393. 
394.ViewBag.ReturnUrl = returnUrl;
395.return View(model);
396.}
397. 
398.//
399.// POST: /Account/LogOff
400.[HttpPost]
401.[ValidateAntiForgeryToken]
402.public ActionResult LogOff()
403.{
404.AuthenticationManager.SignOut();
405.return RedirectToAction("Index", "Home");
406.}
407. 
408.//
409.// GET: /Account/ExternalLoginFailure
410.[AllowAnonymous]
411.public ActionResult ExternalLoginFailure()
412.{
413.return View();
414.}
415. 
416.[ChildActionOnly]
417.public ActionResult RemoveAccountList()
418.{
419.var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
420.ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
421.return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
422.}
423. 
424.protected override void Dispose(bool disposing)
425.{
426.if (disposing && UserManager != null)
427.{
428.UserManager.Dispose();
429.UserManager = null;
430.}
431.base.Dispose(disposing);
432.}
433. 
434.#region Helper
435.// Used for XSRF protection when adding external logins
436.private const string XsrfKey = "XsrfId";
437. 
438.private IAuthenticationManager AuthenticationManager
439.{
440.get
441.{
442.return HttpContext.GetOwinContext().Authentication;
443.}
444.}
445. 
446.private async Task SignInAsync(ApplicationUser user, bool isPersistent)
447.{
448.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
449.var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
450.AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
451.}
452. 
453.private void AddErrors(IdentityResult result)
454.{
455.foreach (var error in result.Errors)
456.{
457.ModelState.AddModelError("", error);
458.}
459.}
460. 
461.private bool HasPassword()
462.{
463.var user = UserManager.FindById(User.Identity.GetUserId());
464.if (user != null)
465.{
466.return user.PasswordHash != null;
467.}
468.return false;
469.}
470. 
471.public enum ManageMessageId
472.{
473.ChangePasswordSuccess,
474.SetPasswordSuccess,
475.RemoveLoginSuccess,
476.Error
477.}
478. 
479.private ActionResult RedirectToLocal(string returnUrl)
480.{
481.if (Url.IsLocalUrl(returnUrl))
482.{
483.return Redirect(returnUrl);
484.}
485.else
486.{
487.return RedirectToAction("Index", "Home");
488.}
489.}
490. 
491.private class ChallengeResult : HttpUnauthorizedResult
492.{
493.public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null)
494.{
495.}
496. 
497.public ChallengeResult(string provider, string redirectUri, string userId)
498.{
499.LoginProvider = provider;
500.RedirectUri = redirectUri;
501.UserId = userId;
502.}
503. 
504.public string LoginProvider { get; set; }
505.public string RedirectUri { get; set; }
506.public string UserId { get; set; }
507. 
508.public override void ExecuteResult(ControllerContext context)
509.{
510.var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
511.if (UserId != null)
512.{
513.properties.Dictionary[XsrfKey] = UserId;
514.}
515.context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
516.}
517.}
518.#endregion
519.}
520.}
修改相关 Views
 
修改Register.cshtml View 
01.@model RoleBaseProject.Models.RegisterViewModel
02.@{
03.ViewBag.Title = "注册";
04.}
05. 
06.<h2>@ViewBag.Title.</h2>
07. 
08.@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
09.{
10.@Html.AntiForgeryToken()
11.<h4>建立新的账户。</h4>
12.<hr />
13.@Html.ValidationSummary()
14.<div class="form-group">
15.@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
16.<div class="col-md-10">
17.@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
18.</div>
19.</div>
20.<div class="form-group">
21.@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
22.<div class="col-md-10">
23.@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
24.</div>
25.</div>
26.<div class="form-group">
27.@Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
28.<div class="col-md-10">
29.@Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
30.</div>
31.</div>
32.<div class="form-group">
33.@Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" })
34.<div class="col-md-10">
35.@Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
36.</div>
37.</div>
38.<div class="form-group">
39.@Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" })
40.<div class="col-md-10">
41.@Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
42.</div>
43.</div>
44.<div class="form-group">
45.@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
46.<div class="col-md-10">
47.@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
48.</div>
49.</div>
50.<div class="form-group">
51.<div class="col-md-offset-2 col-md-10">
52.<input type="submit" class="btn btn-default" value="注册" />
53.</div>
54.</div>
55.}
56. 
57.@section Scripts {
58.@Scripts.Render("~/bundles/jqueryval")
59.}
 
新增Edit、Delete、Index 等方法的Views
 
新增Edit Views
 


 

用以下内容取代原程序

01.@model RoleBaseProject.Models.EditUserViewModel
02. 
03.@{
04.ViewBag.Title = "数据者数据编辑";
05.}
06. 
07.<h2>数据者数据编辑</h2>
08. 
09.@using (Html.BeginForm())
10.{
11.@Html.AntiForgeryToken()
12.<div class="form-horizontal">
13.<h4>修改原有账号数据</h4>
14.<hr />
15.@Html.ValidationSummary(true)
16.<div class="form-group">
17.@Html.LabelFor(model => model.UserName, new { @class = "control-label col-md-2" })
18.<div class="col-md-10">
19.@Html.EditorFor(model => model.UserName)
20.@Html.ValidationMessageFor(model => model.UserName)
21.</div>
22.</div>
23. 
24.<div class="form-group">
25.@Html.LabelFor(model => model.FirstName, new { @class = "control-label col-md-2" })
26.<div class="col-md-10">
27.@Html.EditorFor(model => model.FirstName)
28.@Html.ValidationMessageFor(model => model.FirstName)
29.</div>
30.</div>
31. 
32.<div class="form-group">
33.@Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" })
34.<div class="col-md-10">
35.@Html.EditorFor(model => model.LastName)
36.@Html.ValidationMessageFor(model => model.LastName)
37.</div>
38.</div>
39. 
40.<div class="form-group">
41.@Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
42.<div class="col-md-10">
43.@Html.EditorFor(model => model.Email)
44.@Html.ValidationMessageFor(model => model.Email)
45.</div>
46.</div>
47. 
48.<div class="form-group">
49.<div class="col-md-offset-2 col-md-10">
50.<input type="submit" value="存档" class="btn btn-default" />
51.</div>
52.</div>
53.</div>
54.}
55. 
56.<div>
57.@Html.ActionLink("回到使用者清单画面", "Index")
58.</div>
59. 
60.@section Scripts {
61.@Scripts.Render("~/bundles/jqueryval")
62.}

新增Delete的Views

用以下内容取代原程序

01.@model RoleBaseProject.Models.EditUserViewModel
02. 
03.<h3>使用者账号删除</h3>
04.<div>
05.<h4>确定要删除这个使用者账号?</h4>
06.<hr />
07.<dl class="dl-horizontal">
08.<dt>
09.@Html.DisplayNameFor(model => model.UserName)
10.</dt>
11. 
12.<dd>
13.@Html.DisplayFor(model => model.UserName)
14.</dd>
15. 
16.<dt>
17.@Html.DisplayNameFor(model => model.FirstName)
18.</dt>
19. 
20.<dd>
21.@Html.DisplayFor(model => model.FirstName)
22.</dd>
23. 
24.<dt>
25.@Html.DisplayNameFor(model => model.LastName)
26.</dt>
27. 
28.<dd>
29.@Html.DisplayFor(model => model.LastName)
30.</dd>
31. 
32.<dt>
33.@Html.DisplayNameFor(model => model.Email)
34.</dt>
35. 
36.<dd>
37.@Html.DisplayFor(model => model.Email)
38.</dd>
39. 
40.</dl>
41. 
42.@using (Html.BeginForm()) {
43.@Html.AntiForgeryToken()
44. 
45.<div class="form-actions no-color">
46.<input type="submit" value="删除" class="btn btn-default" /> |
47.@Html.ActionLink("回到使用者清单画面", "Index")
48.</div>
49.}
50.</div>

新增Index Views

用以下内容取代原程序

01.@model IEnumerable<RoleBaseProject.Models.EditUserViewModel>
02. 
03.@{
04.ViewBag.Title = "账号管理";
05.}
06. 
07.<h2>账号管理</h2>
08. 
09.<p>
10.@Html.ActionLink("新增账号", "Register")
11.</p>
12.<table class="table">
13.<tr>
14.<th>
15.@Html.DisplayNameFor(model => model.UserName)
16.</th>
17.<th>
18.@Html.DisplayNameFor(model => model.FirstName)
19.</th>
20.<th>
21.@Html.DisplayNameFor(model => model.LastName)
22.</th>
23.<th>
24.@Html.DisplayNameFor(model => model.Email)
25.</th>
26.<th></th>
27.</tr>
28. 
29.@foreach (var item in Model) {
30.<tr>
31.<td>
32.@Html.DisplayFor(modelItem => item.UserName)
33.</td>
34.<td>
35.@Html.DisplayFor(modelItem => item.FirstName)
36.</td>
37.<td>
38.@Html.DisplayFor(modelItem => item.LastName)
39.</td>
40.<td>
41.@Html.DisplayFor(modelItem => item.Email)
42.</td>
43.<td>
44.@Html.ActionLink("编辑", "Edit", new { id=item.UserName }) |
45.@Html.ActionLink("角色", "UserRoles", new { id=item.UserName }) |
46.@Html.ActionLink("删除", "Delete", new { id=item.UserName })
47.</td>
48.</tr>
49.}
50. 
51.</table>
新增好的三個View
 
 

 
新增UserRoles.cshtml View 并 新增程序代码
 


 

用以下内容取代原程序

01.@model RoleBaseProject.Models.SelectUserRolesViewModel
02.@{
03.ViewBag.Title = "使用者角色";
04.}
05. 
06.<h2>使用者角色 @Html.DisplayFor(model => model.UserName)</h2>
07.<hr />
08. 
09.@using (Html.BeginForm("UserRoles", "Account", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
10.{
11.@Html.AntiForgeryToken()
12. 
13.<div class="form-horizontal">
14.@Html.ValidationSummary(true)
15.<div class="form-group">
16.<div class="col-md-10">
17.@Html.HiddenFor(model => model.UserName)
18.</div>
19.</div>
20. 
21.<h4>选择要加入的角色</h4>
22.<br />
23.<hr />
24. 
25.<table>
26.<tr>
27.<th>
28.勾选
29.</th>
30.<th>
31.角色
32.</th>
33.</tr>
34.@Html.EditorFor(model => model.Roles)
35.</table>
36.<br />
37.<hr />
38. 
39.<div class="form-group">
40.<div class="col-md-offset-2 col-md-10">
41.<input type="submit" value="存档" class="btn btn-default" />
42.</div>
43.</div>
44.</div>
45.}

新增SelectRoleEditorViewModel.cshtml 在 Shared/EditorTemplates目录下

01.@model RoleBaseProject.Models.SelectRoleEditorViewModel
02.@Html.HiddenFor(model => model.RoleName)
03.<tr>
04.<td style="text-align:center">
05.@Html.CheckBoxFor(model => model.Selected)
06.</td>
07.<td>
08.@Html.DisplayFor(model => model.RoleName)
09.</td>
10.</tr>

在主页面上新增”账号管理" 功能按钮

移除主页面上的注册功能

 
 

 
启动 Migration功能
 

 
在Seed()方法中加入建立测试数据的程序代码
 

 
完整程序:

01.namespace RoleBaseProject.Migrations
02.{
03.using RoleBaseProject.Models;
04.using System;
05.using System.Data.Entity;
06.using System.Data.Entity.Migrations;
07.using System.Linq;
08. 
09.internal sealed class Configuration : DbMigrationsConfiguration<RoleBaseProject.Models.ApplicationDbContext>
10.{
11.public Configuration()
12.{
13.AutomaticMigrationsEnabled = false;
14.}
15. 
16.protected override void Seed(RoleBaseProject.Models.ApplicationDbContext context)
17.{
18.// This method will be called after migrating to the latest version.
19. 
20.// You can use the DbSet<T>.AddOrUpdate() helper extension method
21.// to avoid creating duplicate seed data. E.g.
22.//
23.// context.People.AddOrUpdate(
24.// p => p.FullName,
25.// new Person { FullName = "Andrew Peters" },
26.// new Person { FullName = "Brice Lambson" },
27.// new Person { FullName = "Rowan Miller" }
28.// );
29.//
30.this.AddUserAndRoles();
31.}
32. 
33.bool AddUserAndRoles()
34.{
35.bool success = false;
36. 
37.var idManager = new IdentityManager();
38.success = idManager.CreateRole("Admin");
39.if (!success == true) return success;
40. 
41.success = idManager.CreateRole("CanEdit");
42.if (!success == true) return success;
43. 
44.success = idManager.CreateRole("User");
45.if (!success) return success;
46. 
47.var newUser = new ApplicationUser()
48.{
49.UserName = "jatten",
50.FirstName = "John",
51.LastName = "Atten",
52.Email = "jatten@typecastexception.com"
53.};
54. 
55.success = idManager.CreateUser(newUser, "Password1");
56.if (!success) return success;
57. 
58.success = idManager.AddUserToRole(newUser.Id, "Admin");
59.if (!success) return success;
60. 
61.success = idManager.AddUserToRole(newUser.Id, "CanEdit");
62.if (!success) return success;
63. 
64.success = idManager.AddUserToRole(newUser.Id, "User");
65.if (!success) return success;
66. 
67.return success;
68.}
69.}
70.}

更新数据库

执行结果

以具有Admin角色的使用者登入后执行账户管理功能:

在ASP.NET MVC5中建置以角色为基础的授权机制的更多相关文章

  1. ASP.NET MVC5+EF6+EasyUI 后台管理系统-分配角色给用户

    系列目录 由于之前做了将权限赋给角色,还需要做将角色组赋给用户,和将用户赋给角色组,一个用户可以拥有多个角色组,一个角色组包含多个用户,打开模块管理,添加一个分配的操作码 并在 角色权限设置授权给他 ...

  2. ASP.NET MVC5框架揭秘 学习笔记01

    1.自治视图 在早期(作者也没说明是多早,自己猜吧),我们倾向于将所有与UI相关的操作糅合在一起(现在我身边还有很多人这样做),这些操作包括UI界面的呈现. 用户交互操作的捕捉与响应(UI处理逻辑). ...

  3. ASP.NET MVC5 高级编程-学习日记-第一章 入门

    1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...

  4. ASP.NET + MVC5 入门完整教程三 (下) ---MVC 松耦合

    建立松耦合组件 MVC 模式最重要的特性之一视他支持关注分离,希望应用程序中的组件尽可能独立,只有很少的几个可控依赖项.在理想的情况下,每个组件都不了解其他组件,而只是通过抽象接口来处理应用程序的其他 ...

  5. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库  您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB  升级后界面效果如下: 任务调度系统界面 http: ...

  6. 分享阿里云推荐码 IC1L2A,购买服务器可以直接打9折,另附阿里云服务器部署ASP.NET MVC5关键教程

    阿里云推荐码为:IC1L2A 阿里云还是不错滴. 以windows server 2008 R2为例,介绍如何从全新的服务器部署MVC5 站点. 新购买的阿里云服务器是没有IIS的,要安装IIS: 控 ...

  7. ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(1)用户注册

    上一次把基本框架搭建起来了,这次开始整Web部分,终于可以看到界面了小激动一下.web项目部分从用户功能开始,基本有注册,登录.注销.查找.查看.删除等涉及Member区域和Manage区域. 目录: ...

  8. Linux(CentOS 6.5)下配置Mono和Jexus并且部署ASP.NET MVC5

    1.开篇说明 a. 首先我在写这篇博客之前,已经在自己本地配置了mono和jexus并且成功部署了asp.net mvc项目,我也是依赖于在网上查找的各种资料来配置环境并且部署项目的,而其在网上也已有 ...

  9. 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统

    开篇:从50开始系统已经由MVC4+EF5+UNITY2.X+Quartz 2.0+easyui 1.3.4无缝接入 MVC5+EF6+Unity4.x+Quartz 2.3 +easyui 1.4. ...

随机推荐

  1. iOS开发-Alcatraz插件管理

    CocoaPod负责iOS开发中的引用类库的管理,Alcatraz中文翻译阿尔卡特拉斯岛,也有人称之为恶魔岛,主要是负责管理第三方Xcode 插件.模版以及颜色配置的工具,直接集成到 Xcode 的图 ...

  2. Linux档案与目彔的基本操作(查看与权限)

    此文包含的命令: cd.pwd.mkdir.rmdir.rm.ls.cp.mv.cat.tac.more.less.head.tail.od.touch.umask.chattr.lsattr.fil ...

  3. jsp学习---mvc模式介绍和el表达式,jstl标签库的使用入门

    一.mvc模式介绍 下图是常用的mvc分层模式: 项目中的包命名规则,一般如下: com.amos.domain 封装JavaBean,一般我喜欢用model命名这个包com.amos.dao 封装d ...

  4. hdu 3254 (状压DP) Corn Fields

    poj 3254 n乘m的矩阵,1表示这块区域可以放牛,0,表示不能,而且不能在相邻的(包括上下相邻)两个区域放牛,问有多少种放牛的方法,全部不放也是一种方法. 对于每块可以放牛的区域,有放或者不放两 ...

  5. Android Preference使用

    Android Preference经常使用在例如设置的功能,Android提供preference这个键值对的方式来处理这种情况,自动保存这些数据,并立时生效,这种就是使用android share ...

  6. 团队项目作业:利用NABCD模型进行竞争性需求分析

    NABC正是这样的一套框架,当你试图提出一项崭新的提案之际,它能够提供四个思维基点,令你的商业策划具备天马行空的基础. 具体来说,NABC是四个关键词的首字母缩写- Need(需求)-现在市场上未被满 ...

  7. Til the Cows Come Home

    Description Bessie is out in the field and wants to get back to the barn to get as much sleep as pos ...

  8. 2227 邮票--FUoj(链接表+树的直径)

    http://acm.fzu.edu.cn/problem.php?pid=2227 我感觉这道题可以随意搞 题目大意: 给你的一个图就是一条链,但是不知道起始点和结束点,而且每个点只会访问一次. 因 ...

  9. 【洛谷P2296】寻找道路

    反正图两边bfs #include<iostream> #include<cstdio> #include<queue> using namespace std; ...

  10. jQuery in action 3rd - Selecting elements

    jQuery(selector) / $(selector) selector 选择器有多种形式,下面是 #ID,.class,element jQuery 支持的 CSS 层级关系选择器 jQuer ...