在ASP.NET MVC5中建置以角色为基础的授权机制

在前一篇贴文中,已探索过如何在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角色的使用者登入后执行账户管理功能:
 

\

 

转载于:https://www.cnblogs.com/zhouXX/p/4104052.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值