角色是用户分组还是功能分组,我实现的一个按功能分组的角色管理的思考
不管是windows自身的权限,还是asp.net自带的role提供程序,都是实现的用户分组,管理员组也好,普通用户组也好,能实现的功能都是一样的,只不过受到权限的限制,权限低的组人为的屏蔽了一些功能。
考虑我们自己开发的一些管理系统,角色往往是固定的,而功能又是完全不同的,比如学校里,系统一般总有教师角色,学生角色。而教师和学生实现的功能完全是不同的,也许教师是开课,学生是选课,不太可能一个用户即隶属与教师角色,又隶属于学生角色。
在系统的业务逻辑层中,一般的开发似乎也不包含角色的相关信息,只是实现了功能,而谁有调用的权限,交给UI层处理,比如项目的管理,一般总是有个项目管理类 ProjectManage,有Add增加项目方法,Del删除项目方法等,从来不管学生是不能增加项目的权限等情况。
根据以上情况,我实现了一个将登录用户角色和业务逻辑层的角色结合起来的模式。
业务逻辑层弱化项目管理类,强化角色的概念,一个业务逻辑层主要实现各角色相关的功能,比如Teacher类,实现AddProject方法,而Student类,就没有实现这个方法。通过角色基类,实现公共代码的共享,通过一些虚函数,还能减少不少界面的麻烦,比如基类定义GetNavigation方法,各角色重写这个方法,实现各自登录的界面栏目,这样UI就不用判断是什么角色,主要得到这个返回值,格式化一下显示就可以了。
登录验证的时候把角色信息写到Ticket的UserData里去,这儿是Student,根据不同登录情况,设置不同角色。
Dim encTicket As String = FormsAuthentication.Encrypt(ticket)
Response.Cookies.Add(New HttpCookie(FormsAuthentication.FormsCookieName, encTicket))
Response.Redirect(FormsAuthentication.GetRedirectUrl(TextBox1.Text, False))
在登录后,如果有的用户有多个角色,比如,有的教师还是管理员,那么还可以切换一下这个Ticket,就是做个按钮,单击后重新设置UserData,不过登录的用户名就可以直接用User.Identity.Name了。
在业务逻辑层有对应的角色类,基类为UserBase
Private _id As String = String.Empty
Public Property Id() As String
Get
Return _id
End Get
Set(ByVal value As String)
_id = value
End Set
End Property
Private _name As String = String.Empty
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public MustOverride Function GetNavigations() As NavigationCollection
End Class
学生角色,教师角色等分别继承他,并重新GetNavigations等方法。
Public Overrides Function GetNavigations() As NavigationCollection
Dim nc As New NavigationCollection
nc.Add(New Navigation() With {.Title = "项目申请", .Content = "项目申请"})
Return nc
End Function
End Class
Partial Public Class Teacher
Public Overrides Function GetNavigations() As NavigationCollection
Dim nc As New NavigationCollection
nc.Add(New Navigation() With {.Title = "项目开设", .Content = "项目开设"})
Return nc
End Function
End Class
UI做个登录角色和业务逻辑角色的转换
Public Function ToBLLRole(ByVal identity As IIdentity) As BusinessLogicLayer.UserBase
Dim UIRole = CType(identity, FormsIdentity).Ticket.UserData
Select Case UIRole
Case "Student"
Dim s As New BusinessLogicLayer.Student
Dim uu = 取得用户信息的类.GetStudentById(identity.Name)
s.Id = uu.Id
s.Name = uu.Name
Return s
Case "Teacher"
Dim t As New BusinessLogicLayer.Teacher
Dim uu = 取得用户信息的类.GetTeacherById(identity.Name)
t.Id = uu.Id
t.Name = uu.Name
Return t
'这个根据角色不同而增加
Case Else
Throw New ArgumentException
End Select
End Function
页面绑定这个返回值
xxx.DataSource = bllRole.GetNavigations
xxx.DataBind()