关于权限的设计与实现方案

A.左侧菜单

[用户登录后只能看到自己对应权限的菜单]
用户登陆成功后通过用户id进行5表联查查询当前用户对应的所有菜单把查询出的结果。转换成json返回前端页面利用前端构建树形菜单工具展示在页面上。

@ResponseBody
@RequestMapping(value = "/list.do")
public List<Baisi_Menu> getMenusByPid(String menu_id, HttpSession session) {
	if (menu_id == null || menu_id.equals("")) {
		menu_id = 0 + "";
	}
	// session中取出登录的用户
	Baisi_User user = (Baisi_User) session.getAttribute("user");
	//通过用户id获取当前用户对应的所有菜单
	return service.getMenusByPid(menu_id, user.getUser_id());
}

但是用户仍然可以通过拼接url的方式访问到自己没有权限的页面
所以需要进行权限拦截↓↓↓

B.权限拦截

[基于springmvc拦截器实现权限拦截]

  1. 用户登陆后通过用户id拿到当前用户所有菜单权限存放到session中
//通过登录用户id获取所有menu_code
List<String> mlist = mservice.getMenusByUid(user.getUser_id());
session.setAttribute("mlist", mlist);
  1. 声明了一个自定义@PathChange注解
@Target(ElementType.METHOD)//注解作用的地方
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
public @interface PathChange {

	String name() default "";
	
}

3.把自定义的注解放在controller方法上

//注解中需要传入一个请求标识符MENU_CODE
//这样每个菜单对应一个权限
@PathChange(name = "CDGL")
@ResponseBody
@RequestMapping(value = "/getAll.do")
public List<Baisi_Menu> getAll(String menu_id) {
	if (menu_id == null || menu_id.equals("")) {
		menu_id = 0 + "";
	}

	return service.getAll(menu_id);
}

4.在拦截器中先从session中取到当前用户的所有菜单权限List<>

List<String> list = (List<String>) request.getSession().getAttribute("mlist");

5.通过文档得知,第三个参数就是即将调用的控制器方法。于是我们可以通过反射得到@PathChange注解:

HandlerMethod h = (HandlerMethod) handler;
String menu_code = h.getMethodAnnotation(PathChange.class).name();
  • 但是实际运行中发现很严重的问题,那就是handler的实际类型并不总是HandlerMethod类型,因此第一行代码经常会扔ClassCastException。经过研究发现,只有当GET请求是请求静态文件时(在spring配置文件里会配置静态文件的URI),handler的实际类型会是DefaultServletHttpRequestHandler,此时强制转换就会报错。
  • 解决办法
    在执行强制转换之前用instanceof检查参数handler的实际类型。
String menu_code = "";
//检查参数handler的实际类型
if (handler instanceof HandlerMethod) {

	HandlerMethod h = (HandlerMethod) handler;
			
	if (h.getMethodAnnotation(PathChange.class) != null) {
		if (h.getMethodAnnotation(PathChange.class).name() != null
				&& !h.getMethodAnnotation(PathChange.class).name().equals("")) {
				menu_code = h.getMethodAnnotation(PathChange.class).name();
		}
	}
}
  1. 然后拿着取出的MENU_CODE和权限集合List进行对比对比成功则放行,失败则拦截并执行相应操作
if (list.contains(menu_code)) {

	return true;

} else {
	//拦截后的操作
	return false;
}

C.按钮显隐
- 后续…

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值