接四,四里面对权限说了个大概,今天打算将权限好好说说,接下来几个板块将对整个系统的权限做详细介绍,这是整个系统最核心的部分.
刚开始做系统时对权限抱有一颗敬畏的心,一直不敢深究,也没有遇到什么好的权限系统可以学习,前段时间公司开发了个很小的权限管理系统,我正好参与设计了权限设计.刚开始开会讨论时,大家意见不一致,其实都对权限模型不太懂,最后我建议放弃RBAC,倒不是说RBAC不好,而是这个系统是在太小了,就是管理几个其他系统的入口,不同的人登录给他不同的入口就完事了,最后我刚好接触过一个权限模型,就用了!大概思想是这样的,在页面分配权限时,每个人都有一个权限字符串,长度和所有的要控制的入口一样,位数一一对应,谁有这个权限,对应为就为1,在页面分配权限时,对这几个系统勾选,如果勾选了,在后在就用js构造出对应的字符串,然后保存到对应的管理员表中,这个方法很简单,但是很实用,只适合小型的系统,如果权限字符串过长的话,就不好控制了.
var teipprim ="";
//构造权限字符串
function checkPrim(){
for (var i=1;i<11;i++){
c = "0";
tempid = "prim"+i;
if (document.getElementById(tempid).checked == true)c = "1";
teipprim = teipprim+c;
}
if (teipprim!='000000000000000'){
document.all.privileges.value = teipprim;
}else{
document.all.privileges.value = "";
}
}
//还原权限列表
function recoverPrim(temp){
if (teipprim=='000000000000000'){
document.all.privileges.value = "";
return;
}else{
for (var i=0;i<10;i++){
if (temp.substring(i,i+1)=="1")document.getElementById("prim"+(i+1)).checked = true;
}
}
}
然后登陆时采用拦截器,代码如下:
public class LoginedCheckInterceptor extends AbstractInterceptor {
/** 拦截请求并进行登录有效性验证 */
public String intercept(ActionInvocation ai) throws Exception {
//取得请求的URL
String url = ServletActionContext.getRequest().getRequestURL().toString();
System.out.println(url);
String prim = null;
Admin admin = null;
int index = 0;
//验证Session是否过期
if(!ServletActionContext.getRequest().isRequestedSessionIdValid()){
//session过期,转向session过期提示页,最终跳转至登录页面
return "tologin";
}else{
//对登录与注销请求直接放行,不予拦截
if (url.indexOf("admin_login.action")!=-1 || url.indexOf("admin_logout.action")!=-1){
return ai.invoke();
}else{
admin = (Admin)ServletActionContext.getRequest().getSession().getAttribute("admin");
//验证是否已经登录
if (admin==null){
//尚未登录,跳转至登录页面
return "tologin";
}else{
//功能模块与权限位映射,部分可能与前台请求重名的请求加上命名空间"/admin"以示区别
if (url.indexOf("/admin_")!=-1 || url.indexOf("/updateAdmin")!=-1){//系统用户管理
index = 2; //权限位为2
}else if (url.indexOf("/columns_")!=-1 || url.indexOf("/updateColumns")!=-1){//新闻栏目管理
index = 3; //权限位为3
}else if (url.indexOf("/news_")!=-1 || url.indexOf("/preAddNews")!=-1 || url.indexOf("/updateNews")!=-1 || url.indexOf("/publisNews")!=-1){//新闻管理
index = 4; //权限位为4
}else if (url.indexOf("/rule_")!=-1 || url.indexOf("/preAddNewsrule")!=-1 || url.indexOf("/updateNewsrule")!=-1){ //新闻采集
index = 5; //权限位为5
}else if (url.indexOf("/level_")!=-1 || url.indexOf("/updateMemberlevel")!=-1){//会员级别管理
index = 6; //权限位为6
}else if (url.indexOf("/member_")!=-1 || url.indexOf("/preAddMember")!=-1 || url.indexOf("/admin/updateMember")!=-1){//会员管理
index = 6; //权限位为6
}else if (url.indexOf("/cate_")!=-1 || url.indexOf("/updateCategory")!=-1){//商品分类管理
index = 7; //权限位为7
}else if (url.indexOf("/mer_")!=-1 || url.indexOf("/preAddMerchandise")!=-1 || url.indexOf("/updateMerchandise")!=-1 || url.indexOf("/publisMerchandise")!=-1){//商品管理
index = 8; //权限位为8
}else if (url.indexOf("/orders_")!=-1 || url.indexOf("/admin/updateOrdersStatus")!=-1){//订单管理
index = 9; //权限位为9
}else if (url.indexOf("/traffic_")!=-1){//流量统计
index = 10; //权限位为10
}
//取得当前用户的操作权限
prim = admin.getPrivileges().trim();
if (index>0){
if (prim.substring(0,1).equals("1") || prim.substring(index-1,index).equals("1")){
return ai.invoke();
}else{
return "nopm";
}
}else{
return ai.invoke();
}
}
}
}
}
}
这是我遇到最简单的形式,但是不够灵活,我觉得如果页面链接全部写死了用这个也可以!
下面详细谈谈这个论坛用的权限模型:
再贴一次图吧:
这个图有一点问题,Board和BoardPermission之间最后实现时没有对应关系,BoardPermission类的结构如下,它只是保存了Board和UserGroup的对应关系,并不是以对象的形式声明的.只是和Permission类有关联关系.而且大家也看出来了,这个系统的Board类的id是long类型的,group是String类型的,印证了我在[三]里面的结论.
public class BoardPermission implements Serializable {
private String id;
private long boardID;
private String groupID;
private Set permissions;
}
这个论坛权限分为两条主线,今天来谈谈第一条线,也就是上面那条线:
主要涉及版区权限,下次谈个人权限.先看看创建一个版区时的代码:
public void createBoard(Board board) {
this.getDao().saveOrUpdate(board);
List uglist = this.getDao().listAll("UserGroup", "id", Constant.ASC);
BoardPermission bp;
for (int i = 0; i < uglist.size(); i++) {
UserGroup ug = (UserGroup) uglist.get(i);
bp = new BoardPermission();
bp.setBoardID(board.getId());
bp.setGroupID(ug.getId());
switch (ug.getType()) {
case 0://游客
bp.setPermissions(SystemInit.gbp0);
break;
case 1://注册用户
bp.setPermissions(SystemInit.gbp1);
break;
case 2://等待验证用户组
bp.setPermissions(SystemInit.gbp2);
break;
case 3:// 超级版主
bp.setPermissions(SystemInit.gbp3);
break;
case 4:// 系统管理员
bp.setPermissions(SystemInit.gbp4);
break;
case 5:// 封禁用户
bp.setPermissions(SystemInit.gbp5);
break;
default:
bp.setPermissions(SystemInit.gbp0);
}
this.getDao().saveOrUpdate(bp);
}
}
一句话解释:对于每个用户组,在创建版区时都为其创建了版区对应的权限.下面是SystemInit的一段代码,便于对上面代码理解.
public class SystemInit {
private static PermissionService permissionService;
static{
ApplicationContext acx = new ClassPathXmlApplicationContext("app*.xml");
permissionService = (PermissionService) acx.getBean("permissionService");
}
// resource,action
public static Permission p000 = new Permission("注册权限","/userInfo", "reg,regSave",2);
public static Permission p101 = new Permission("发帖权限", "/forum", "post,postSave", 2);
public static Permission p102 = new Permission("查看主帖列表权限", "/forum", "listForums", 2);
public static Permission p103 = new Permission("查看精华帖列表权限", "/forum", "listForumsElite", 2);
public static Permission p201 = new Permission("查看帖子权限", "/forum", "readForum", 2);
public static Permission p202 = new Permission("回复帖子权限", "/forum", "reSave,reQuote", 2);
public static Permission p203 = new Permission("编辑自己帖子权限", "/forum", "editForum,editForumSave" , 2);
public static Permission p401 = new Permission("版主管理权限", "/forum", "manager", 2);
public static Permission p402 = new Permission("版主发布公告权限", "/forum", "postBulletin,postBulletinSave", 2);
public static Permission p403 = new Permission("版主删除帖子权限", "/forum", "deleteForum", 2);
public static Permission p404 = new Permission("版主加精帖子权限", "/forum", "doElite", 2);
//用户组版区权限
public static Set gbp0= new HashSet();//未注册用户
public static Set gbp1= new HashSet();//注册用户
public static Set gbp2= new HashSet();//带验证用户
public static Set gbp3= new HashSet();//超级版主
public static Set gbp4= new HashSet();//超级管理员
public static Set gbp5= new HashSet();//封禁用户
static{
//对权限保存代码省略
gbp0.add(p000);//未注册用户
gbp0.add(p102);
gbp0.add(p201);
//
gbp1.add(p000);//注册用户
gbp1.add(p101);
gbp1.add(p102);
gbp1.add(p103);
gbp1.add(p201);
gbp1.add(p202);
gbp1.add(p203);
//
gbp3.add(p401);//超级版主
gbp3.add(p402);
gbp3.add(p403);
gbp3.add(p404);
gbp4.add(p000);//系统管理员
gbp4.add(p101);
gbp4.add(p102);
gbp4.add(p103);
gbp4.add(p201);
gbp4.add(p202);
gbp4.add(p203);
gbp4.add(p401);
gbp4.add(p402);
gbp4.add(p403);
gbp4.add(p404);
}
}
权限类型有四种,个人权限(0),个人特殊权限(1),版区权限(2),版区特殊权限(3),括号里为权限类型.这样就会有一个表来保存board和permission之间多对多的关系,访问页面时使用拦截器获取访问者所在用户组和用户要访问的版区id,这样就可以获取到对应的版区权限,代码如下:
public class BoardInterceptor extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
Object action = invocation.getAction();
String actionName = "/"+ac.getName();
String saction = "";
Map map = ac.getParameters();
String[] _saction = (String[]) map.get("action");
if (_saction != null) {
saction = _saction[0];
}
long bid = 0;
String[] _bid = (String[]) map.get("bid");
if (_bid != null) {
bid = NumberUtils.toLong(_bid[0], 0);
}
ServletContext servletContext = (ServletContext) ac.get(ServletActionContext.SERVLET_CONTEXT);
WebApplicationContext wc = WebApplicationContextUtils.getWebApplicationContext(servletContext);
if(bid==0){//版区错误
System.out.println("版区错误bid=0");
}
BoardService boardService = (BoardService)wc.getBean("boardService");
Board board = boardService.getBoardByID(bid);
if(board==null){
System.out.println("版区错误board=null");
}
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) ac.get(ServletActionContext.HTTP_RESPONSE);
UserSession us = (UserSession) ac.getSession().get(Constant.USERSESSION);
if(us.getBid()!=bid){
us.getBoardPermission().clear();
us.getSpecialPermission().clear();
us.setBid(bid);
System.out.println("BoardInterceptor.bid:"+bid);
System.out.println("BoardInterceptor.groupID:"+us.getGroupID());
Map[] maps = boardService.getBoardPermissions(bid, us.getGroupID());
us.setBoardPermissionArray(maps);
Iterator it = board.getBoardMaster().iterator();
BoardMaster bmt;//版主
while(it.hasNext()){
bmt = (BoardMaster) it.next();
if(bmt.getUserName().equals(us.getUserName())){//是斑竹
us.setIsBoardMaster(1);
Map[] bmpMap = boardService.getBoardMasterPermission(bmt.getRole());
System.out.println(bmpMap[0].entrySet().size());
us.setBoardPermissionArray(bmpMap);
System.out.println("设置成功");
}
}
//此处省略父版区权限
ac.getSession().put(Constant.USERSESSION, us);
//BoardMaster bm = board.getBoardMaster().addAll(c);
}
boolean havaPermission = false;
Permission permission = (Permission) us.getBoardPermission().get(actionName + "?action=*");
if(permission!=null){
havaPermission = true;
}else{
permission = (Permission) us.getBoardPermission().get(actionName+"?action="+saction);
if(permission!=null){
havaPermission = true;
}else{
System.out.println("saction 为获得");
}
}
if(havaPermission){
//此处添加BoardAware
return invocation.invoke();
}else{
StringBuffer sb = new StringBuffer();
sb.append(BBSNSUtil.getWebRealPath(request));
sb.append(request.getContextPath());
sb.append("/");
sb.append(BBSNSUtil.getActionMappingURLWithoutPrefix(ac.getName()));
UrlHelper.buildParametersString(map, sb, "&");
String curl = sb.toString();
System.out.println("curl:"+curl);
ac.getValueStack().set("tourl", curl);
return "nopermission";
}
}
}
拦截器中最重要的一个方法代码如下:
private Map[] getPermissions(long bid, String groupid) {
Map[ ] boardPermission = { new HashMap(), new HashMap() };
Map mps = new HashMap();
mps.put("boardID", bid);
mps.put("groupID", groupid);
List _list = this.getDao().findByValue("BoardPermission", mps, "id", Constant.ASC);
BoardPermission bp = null;
if (!_list.isEmpty()&&_list!=null) {
bp = (BoardPermission) _list.get(0);
}
Set bps = bp.getPermissions();
if (bps != null) {
Iterator it = bps.iterator();
while (it.hasNext()) {
Permission permission = (Permission) it.next();
if (permission.getTypeID() == 2) {//版区权限
boardPermission[0].put(permission.getResource() + ","+ permission.getAction(), permission);
}
if (permission.getTypeID() == 3) {//版区特殊权限
boardPermission[1].put(permission.getId(), permission);
}
}
} else {
System.out.println("boardPermission 为空!!!"+bps.size());
}
return boardPermission;
}
这个getPermissions方法就是采用我在[二]里面说的那种无耦合的传Map的方法.这样
如果得到对应的版区权限就表明用户所在用户组有这个版区的访问权限.
好了,快下班了,也不知道说清楚了没.如果有什么问题,欢迎留言讨论,个人权限下次再讨论.
原创首发,谢谢支持!
分享到:
相关推荐
在“空中鼠标控制——抛砖引玉”这个项目中,核心是利用双目摄像头来获取用户的手部或任何指定物体的三维空间坐标。双目摄像头,顾名思义,是由两个摄像头组成,通过三角测量原理来计算物体与摄像头之间的距离。它的...
算法优化抛砖引玉-主要是一些算法的实现
1. 理想监控系统的五个关键特性: - 完善的管理系统:能够一目了然地展现系统状态,帮助运维人员快速定位问题。 - 强大的配置系统:可以实现对监控对象的全面监控,确保监控的覆盖面。 - 体贴的过滤系统:智能...
【房地产兵法论专集之二十-抛砖引玉】这篇文档虽然以古代战争中的兵法故事开场,但实质上是探讨房地产市场的策略和现象。"抛砖引玉"原指用普通物品吸引更高价值的物品,文中以此比喻房地产市场中高价房产的价值与其...
这份"抛砖引玉熊市主图"文档提供的源码,就是一个实例,展示了如何通过计算和分析价格、成交量等数据来评估市场的牛熊状态。 首先,公式中的"SW1"是一个短期和长期移动平均线的综合指标,它是5日指数移动平均线...
小弟不才,斗胆写下几行代码,来这里期待抛砖引玉。 我们身边,每天都有无数的项目开工,然后是老板对进度的紧追不舍,项目经理程序员加班的无奈,再然后或许是成功的喜悦或许是失败的哀愁,但不管结果如何,所有...
这是梦幻西游使用的was文件的查看工具,在编写时看了不少WasTools的代码,终于对was文件有个初步的了解了,在查看挑选图片时比原作者云风的waskey方便一点,但运行时间一长就会冒出个Out of system resource的错误,...
从零开始深度学习:TinyMind汉字书法识别 操作步骤 从官网下载,并解压到当前文件夹。产生train test1 两个文件 运行data.py文件,进行转录,将原始数据集转录为numpy矩阵,生成data.npy及label.npy 运行train.py...
小弟不才,斗胆写下几行代码,来这里期待抛砖引玉。我们身边,每天都有无数的项目开工,然后是老板对进度的紧追不舍,项目经理程序员加班的无奈,再然后或许是成功的喜悦或许是失败的哀愁,但不管结果如何,所有人...
1.拷贝CANBus文件夹到D:\WINCE600\PLATFORM\SMDK6410\SRC\DRIVERS 目录下 2.在dirs文件中添加CANBus ...注意:驱动中默认波特率为100K,本源码只是个抛砖引玉的作用。可以根据项目实际情况加以修改。
小弟不才,斗胆写下几行代码,来这里期待抛砖引玉。我们身边,每天都有无数的项目开工,然后是老板对进度的紧追不舍,项目经理程序员加班的无奈,再然后或许是成功的喜悦或许是失败的哀愁,但不管结果如何,所有人...
#### 五、整理数据 ##### 5.1 数据集选项 SAS数据集可以包含各种选项,如变量名、变量类型等。 ##### 5.2 在数据步中整理数据集 - **数据转换**: 使用赋值语句进行数据转换。 - **变量创建**: 可以在数据步中创建...
此资源为抛砖引玉,仅为赶时间速成的同学提供完整的项目案例。 ------------------------------------------------------------- 执行项目需要提前安装好python环境(anaconda、pycharm)以及selenium依赖包(pip ...
最外围一个实心圆,圆里面有一个实心正五角星,五角星的最里面有一个虚线圆,图形的大小和位置随意。一行命令完成,并提供该行命令。 ------------------------ 是个朋友叫我写的,代码里不足之处很多,希望大家谅解...
- 创建用于上传临时文件和会话保存的目录,并设置适当的权限。 3. **配置Apache以支持PHP**: - 在`c:\apache2\conf\httpd.conf`文件中添加以下内容以启用PHP模块和支持: ```ini LoadModule ...
拿代码出来,抛砖引玉吧 主要演示了一些查询技巧,里面的综合评测成绩是这样算的 综合评测(一个学期) 课程*课时/总课时*70%+体育*10%+品德 ============================================================== ...
WPF是微软新一代图形系统,运行在.NET Framework 3.0架构下,为用户界面、2D/3D 图形、文档和媒体提供了统一的描述和操作方法。基于DirectX 9/10技术的WPF不仅带来了前所未有的3D界面,而且其图形向量渲染引擎也大大...
针对开关电源很多人觉得很难,其实不然。设计一款开关电源并不难,难就难在做精,等你真正入门了,积累一定的经验,再采用分立的结构进行设计就...万事开头难,笔者在这就抛砖引玉,慢慢讲解如何一步一步设计开关电源。