[C#][ASP.NET MVC]實做成員和角色管理
在網站安全管理方面,ASP.NET2.0以後提供兩大API(Membership、Role),
幫助開發人員快速建立相關安全管理機制,
而MVC架構下我們當然也可以利用這兩大API實做管理機制,
自己覺得整體開發時間還滿快的(拜MVC所賜XD),這裡記錄一下。
Add SystemController
公開成員相關屬性
#region 成員相關屬性
public class UserAttribute
{
public Guid key { get; set; }
public String Username { get; set; }
public String Lastlogindate { get; set; }
}
public class CreateAttribute : UserAttribute//繼承UserAttribute
{
public String Password { get; set; }
public String Confirmpw { get; set; }
public String Email { get; set; }
}
public class DetailsAttribute : CreateAttribute//繼承CreateAttribute
{
public String Comment { get; set; }
public bool Isapproved { get; set; }
public String Createdate { get; set; }
public String Lastactivitydate { get; set; }
public String Lastlockoutdate { get; set; }
}
public class EditAttribute : DetailsAttribute//繼承DetailsAttribute
{
public bool IslockedOut { get; set; }
public String Lastpasswordchangeddate { get; set; }
}
#endregion
Add SystemRepository
public class SystemRepository
{
public List<UserAttribute> GetAllusers()
{
List<UserAttribute> users = new List<UserAttribute>();
foreach (MembershipUser t in Membership.GetAllUsers())
{
users.Add(//循環設定公開屬性(UserAttribute class in controller)
new UserAttribute
{
key = (Guid)t.ProviderUserKey,
Username = t.ToString(),
Lastlogindate=t.LastLoginDate.ToString("yyyy/MM/dd hh:mm:ss")
});
}
return users;
}
public List<DetailsAttribute> Detailsusers(Guid key)
{
List<DetailsAttribute> Details = new List<DetailsAttribute>();
var user = Membership.GetUser(key);//依照key取得成員相關資訊
Details.Add(//設定公開屬性(DetailsAttribute class in controller)
new DetailsAttribute
{
Username = user.UserName,
key = (Guid)user.ProviderUserKey,
Email = user.Email,
Comment = user.Comment,
Isapproved = user.IsApproved,
Createdate = user.CreationDate.ToString("yyyy/MM/dd hh:mm:ss"),
Lastlogindate = user.LastLoginDate.ToString("yyyy/MM/dd hh:mm:ss"),
Lastactivitydate = user.LastActivityDate.ToString("yyyy/MM/dd hh:mm:ss"),
Lastlockoutdate = user.LastLockoutDate.ToString("yyyy/MM/dd hh:mm:ss")
});
return Details;
}
public List<EditAttribute> Editusers(Guid key)
{
List<EditAttribute> Edits = new List<EditAttribute>();
var user = Membership.GetUser(key);//依照key取得成員相關資訊
Edits.Add(//設定公開屬性(EditAttribute class in controller)
new EditAttribute
{
Username = user.UserName,
key = (Guid)user.ProviderUserKey,
Email = user.Email,
Comment = user.Comment,
Isapproved = user.IsApproved,
IslockedOut=user.IsLockedOut,
Createdate=user.CreationDate.ToString("yyyy/MM/dd hh:mm:ss"),
Lastpasswordchangeddate = user.LastPasswordChangedDate.ToString("yyyy/MM/dd hh:mm:ss")
});
return Edits;
}
}
Index In Controller
[NonAction]//新增自訂Url Routing
protected RedirectToRouteResult RedirectToUserPage( MembershipUser user )
{
var rvd = new RouteValueDictionary( new
{
controller = ControllerContext.RouteData.Values[ "controller" ],
action = "Edit",
key = ( Guid ) user.ProviderUserKey
} );
return RedirectToRoute( rvd );
}
SystemRepository systemrepository = new SystemRepository();
// GET: /System/
//[Authorize(Roles = "Administrators")]//屬於Administrators才有權限
public ActionResult Index()
{
ViewData["Roles"] = Roles.GetAllRoles().ToList();
return View(systemrepository.GetAllusers());//指向systemrepository
}
編寫virtual method for role
#region virtual method for role
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult CreateRole(String name)
{
Roles.CreateRole(name);//建立新角色
return RedirectToAction("Index");
}
public virtual ActionResult DeleteRole(String name)
{
Roles.DeleteRole(name);//刪除角色
return RedirectToAction("Index");
}
public virtual ActionResult AdduserTorole( Guid key, String roleName )
{
var user = Membership.GetUser(key);
Roles.AddUserToRole(user.UserName, roleName);//成員加入特定角色中
return RedirectToUserPage( user );
}
public virtual ActionResult RemoveuserFromrole( Guid key, String roleName )
{
var user = Membership.GetUser(key);
Roles.RemoveUserFromRole(user.UserName, roleName);//移除特定角色中的成員
return RedirectToUserPage( user );
}
#endregion
Add Index View
只列出須自行編寫的表現層code
<fieldset>
<legend>角色</legend>
<% if( (ViewData["Roles"] as List<String>).Count > 0 ){ %>
<ul>
<% foreach( String role in (ViewData["Roles"] as List<String>) ){ %>
<li>[<% =Html.ActionLink("刪除", "DeleteRole", "System", new { name = Html.Encode(role) }, new { onclick = "return confirm('確定要刪除嗎?')" })%>]
<% =Html.ActionLink(Html.Encode(role).ToString(), "Role", "System", new { id =Html.Encode(role) }, null)%>
</li>
<% } %>
</ul>
<% }else{ %>
<div>系統中未存在任何角色</div>
<% } %>
<% using (Html.BeginForm("CreateRole","System"))
{%>
新角色名稱:<% =Html.TextBox("name")%>
<input type="submit" value="建立" />
</fieldset>
<%} %>
新增Guest角色
刪除Guest角色
Details In Controller
public ActionResult Details(Guid key)
{
return View(systemrepository.Detailsusers(key));
}
Add Details View
須自行修改Details參數部分
....
.......
........
<p>
最後鎖定日期:
<%= Html.Encode(item.Lastlockoutdate)%>
</p>
</fieldset>
<p>
<%=Html.ActionLink("Edit", "Edit", new { key = item.key })%> |
<%=Html.ActionLink("Back to List", "Index")%>
</p>
<%} %>
Create In Controller
public ActionResult Create()
{
return View();
}
//
// POST: /System/Create
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Create( FormCollection collection )
{
try
{
MembershipCreateStatus status = MembershipCreateStatus.UserRejected;
MembershipUser user = null;
if( collection[ "Password" ].Equals( collection[ "Confirmpw" ], StringComparison.CurrentCultureIgnoreCase ) )
{
user = Membership.CreateUser( collection[ "Username" ], collection[ "Password" ], collection[ "Email" ], null, null, true, out status );
}
if( status == MembershipCreateStatus.Success )
return RedirectToAction( "Index" );
else
return RedirectToAction( "Error" );
}
catch
{
return View( "Error" );
}
}
編寫virtual method for member
#region virtual method for member
public virtual RedirectToRouteResult UnlockUser( Guid key )
{
var user = Membership.GetUser(key);
user.UnlockUser();//解除鎖定
return RedirectToUserPage( user );
}
public virtual ActionResult DeleteUser(Guid key)
{
var user = Membership.GetUser(key);
Membership.DeleteUser(user.UserName, true);//刪除成員
return RedirectToAction("Index");
}
#endregion
Add Create View
新增test123成員
刪除test123成員
Edit In Controller
// GET: /System/Edit/5
public ActionResult Edit(Guid key)
{
var user = Membership.GetUser(key);
ViewData["AllRoles"] = Roles.GetAllRoles().OrderBy(x => x).ToList();
ViewData["UsersRoles"] = Roles.GetRolesForUser(user.UserName).OrderBy(x => x).ToList();
return View(systemrepository.Editusers(key));//指向systemrepository
}
//
// POST: /System/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit( Guid key, FormCollection collection )
{
try
{
var user = Membership.GetUser(key);
//設定白名單
UpdateModel( user, new[] { "Email", "Comment", "Isapproved" },
collection.ToValueProvider() );
Membership.UpdateUser(user);//更新
return RedirectToUserPage( user );
}
catch
{
return RedirectToAction( "Error" );
}
}
編寫virtual method for password
#region virtual method for password
public virtual ViewResult ResetPassword()
{
String userName = Request.Form["UserName"];
var user = Membership.GetUser(userName);
var pwd = user.ResetPassword(null);
ViewData["newpw"] = pwd;
return View();
}
#endregion
Add Edit View
只列出須自行編寫的表現層code
由於controller傳給view含有list類型,所以實做IList泛型集合,並循環顯示出相關資料。
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%
var allRoles = (IList)ViewData["AllRoles"];
var usersRoles = (IList)ViewData["UsersRoles"];
%>
.....
......
<% using( Html.BeginForm( "ResetPassword", "System" ) )
{ %>
<fieldset>
<legend>密碼修改</legend>
<% foreach( var item in Model )
{ %>
<% =Html.Hidden( "Username", Html.Encode( item.Username ) )%>
<div>
<label>最近密碼變更時間:</label>
<div><% =item.Createdate != item.Lastpasswordchangeddate ? item.Lastpasswordchangeddate : "從未變更密碼"%></div>
</div>
<div><input type="submit" value="重設" /></div>
</fieldset>
<%} %>
<%} %>
<fieldset>
<legend>角色修改</legend>
<% if( ( ( IList ) ViewData[ "AllRoles" ] ).Count > 0 )
{ %>
<% foreach( String role in allRoles )
{ %>
<% foreach( var item in Model )
{ %>
<div>
<% if( usersRoles.Contains( role ) )
{ %>
[<% =Html.ActionLink( "移除", "RemoveuserFromrole", "System", new
{
key = Html.Encode(item.key ),
roleName = Html.Encode( role )}, null )%>]<% }
else
{ %>
[<% =Html.ActionLink( "加入", "AdduserTorole", "System", new
{
key = Html.Encode(item.key ),
roleName = Html.Encode( role )}, null )%>]
<% } %>
<% =Html.ActionLink( role, "Role", "System", new
{
id = Html.Encode( role )}, null )%>
<%} %>
</div>
<% } %>
<% }
else
{ %>
<div>還未加入任何角色</div>
<% } %>
</fieldset>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
編輯test123
重設test123密碼(實際應用上勿使用預設加密演算法)
Add ResetPassword View
<h2>ResetPassword</h2>
<fieldset>
<legend>重新產生密碼</legend>
<p>新密碼:<b><% =Html.Encode(ViewData["newpw"])%></b></p>
</fieldset>
將test123加入 Normal角色中
這樣就完成了成員和角色管理功能了。
賀!一百篇達成
自己從去年8月加入點部落格後,藉由寫部落格文章提升自己,也認識了很多同好
收穫說真的還不少,期望自己在往後的日子能繼續持續下去,最後,先預祝大家虎年行大運。