版权声明:本文为博主原创文章,未经博主允许不得转载。
最近公司布置了一个任务,通过springMVC注解来控制一个请求的权限;由于之前没有接触过注释控制权限,这次尝试了;效果还不是特别好;只能进行简单的权限管理,当然这只是第一版,肯定后面要修改很多方面,希望大神们多多指导;
权限这没用用到最近比较火的shiro框架,还是基于RBAC模型 ,有六张表;
用户表 user 角色表 菜单表 资源表 还有2张关系表
①自定义注解(目前为了简单只定义了一个注解,后期还要再加):
//用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败。 @Target(ElementType.METHOD) //作用范围为运行时,就是我们可以通过反射动态获取该注解。 @Retention(RetentionPolicy.RUNTIME) public @interface RequiresPermission { String value() default "user"; }
②写拦截器(注:目前还没有处理没有权限的跳转页面)
public class RequiresPermissionInterceptor extends HandlerInterceptorAdapter { @Autowired private PermissionService permissionService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler.getClass().isAssignableFrom(HandlerMethod.class)) { //通过反射得到权限的角色 //角色分为三种 user:用户 admin:管理员 superAdmin:超级管理员 RequiresPermission permission = ((HandlerMethod) handler).getMethodAnnotation(RequiresPermission.class); String value = permission.value(); System.out.print("角色"+value); //通过反射拿到requestMapping 里面的value参数 RequestMapping annotation=((HandlerMethod) handler).getMethodAnnotation(RequestMapping.class); System.out.print(annotation.toString()); String[] rm= annotation.value(); //拿到当前请求的地址 String url =request.getServletPath(); String wholeUrl=""; for (int i=0;i<rm.length;i++){ wholeUrl = splitString(url)+rm[i]; System.out.println("wholeUrl完整的url是:"+wholeUrl); } //没有注明权限 或者权限为user 则都默认为用户的权限 if (permission == null || "user".equals(value) ) { System.out.println("我进来了"); //获得用户的roleType Integer roleType =RoleTypeConstant.ROLE_USER; System.out.println("用户的roleType"+roleType); RoleFunction roleFunction =permissionService.findByUrlAndCode(wholeUrl,roleType); if(roleFunction!=null){ return true; } }else if ("admin".equals(value)){ //获得管理员的roleType Integer roleType =RoleTypeConstant.ROLE_ADMIN; System.out.println("管理员的roleType"+roleType); RoleFunction roleFunction =permissionService.findByUrlAndCode(wholeUrl,roleType); if(roleFunction!=null){ return true; } }else if ("superAdmin".equals(value)){ //获得超级管理员的roleType Integer roleType =RoleTypeConstant.ROLE_SUPER_ADMIN; System.out.println("超级管理员的roleType"+roleType); RoleFunction roleFunction =permissionService.findByUrlAndCode(wholeUrl,roleType); if(roleFunction!=null){ return true; } } } return false; } //截取字符串 private String splitString(String url){ //获得第二个/的下标 int subscript= url.indexOf("/",2) ; System.out.println("subscript"+subscript); //截取第二个/前面的字符串 String subUrl= url.substring(0,subscript); System.out.println("SubUrl是"+subUrl); return subUrl; } }
注:RoleTypeConstant调用的方法
public class RoleTypeConstant { /** * 超级管理员账户 */ public static final Integer ROLE_SUPER_ADMIN = 1; /** * 普通管理员账户 */ public static final Integer ROLE_ADMIN = 2; /** * 普通注册用户账户 */ public static final Integer ROLE_USER = 3; public static String getTypeName(Integer roleType){ String typeName = ""; switch (roleType){ case 1 : typeName = "超级管理员"; break; case 2 : typeName = "普通管理员"; break; case 3 : typeName = "普通注册用户"; break; } return typeName; }
注:service层的实现
@Service("permissionService") public class PermissionServiceImpl implements PermissionService{ @Autowired private PermissionDomainService permissionDomainService; @Override public RoleFunction findByUrlAndCode(String url,Integer roleType) { //如果地址为直接返回用户的权限 if (url!=null){ System.out.println("url" +url); //通过查找url获得function对象 Function function =permissionDomainService.findFunctionByUrl(url); System.out.println("function" +function.getCode()); // 通过url获得用户唯一的code Integer code = function.getCode(); if (code!=null ){ //通过获得code 和 roleType 判断RoleFunction是否为null //roleType 分为三种 1:超级管理员 2:管理员 3:用户 RoleFunction roleFunction =permissionDomainService.findByCode(code,roleType); return roleFunction; } } return null; } }
dao层(实现方式不同,这里我只说明接口)
public interface PermissionDao { //通过url获得用户唯一的code public Function queryFunctionByUrl(String url); //通过code 获得用户的rolType 从而控制权限 //roleType 分为三种 1:超级管理员 2:管理员 3:用户 public RoleFunction queryByCode(Integer code,Integer roleType); }
③配置文件里添加扫描拦截器
<mvc:interceptors> <!-- 国际化操作拦截器 如果采用基于(请求/Session/Cookie)则必需配置 --> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <!-- 如果不定义 mvc:mapping path 将拦截所有的URL请求 --> <!--拦截器处理用户登陆的权限 --> <!--<bean class="com.zhongqi.permission.Intercepter.RequiresUserInterceptor"></bean>--> <!--拦截器处理资源的权限 --> <bean class="com.zhongqi.permission.Intercepter.RequiresPermissionInterceptor"></bean> </mvc:interceptors>
控制层的测试()
@Controller @RequestMapping("/match") public class PermissionController extends BaseController { @Autowired private PermissionService permissionService; /** * 测试 从数据库的资源列表查找 * user 的权限 /user/loginOut * 管理员特有的权限 /match/modifyMatchEvent * 超级管理员特有的权限 * * * @param response */ @RequiresPermission("user") @RequestMapping("/loginOut") private void PermissionText1(HttpServletResponse response){ JsonResponseResult result = new JsonResponseResult(); result.setCode(1); result.setMsg("输入正确"); //公司内部封装 response(BaseUtils.toJsonFromObject(result), response); } @RequiresPermission("user") @RequestMapping("/modifyMatchEvent") private void PermissionText2(HttpServletResponse response){ JsonResponseResult result = new JsonResponseResult(); result.setCode(1); result.setMsg("输入正确"); //公司内部封装 response(BaseUtils.toJsonFromObject(result), response); } @RequiresPermission("superAdmin") @RequestMapping("/pt3") private void PermissionText3(HttpServletResponse response){ JsonResponseResult result = new JsonResponseResult(); result.setCode(1); result.setMsg("输入正确"); //公司内部封装 response(BaseUtils.toJsonFromObject(result), response); }
注:目前只是简单的实现了权限控制,还有很多问题没有解决,因为这只是一个人的想法,还有注释里面的参数应该可以再丰富些。目前注释里面只有三个参数,或者不填;通过里面的注释可以判断这个请求是否可以继续下去,就是拦截器;
刚刚开始做,写的特别low,希望大神们多多指导。后期会持续更新改版后的权限管理,欢迎大家访问,希望给刚入手的程序员有所帮助。
2016 /09/09