一、权限管理
1.1什么是权限管理
基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
权限管理包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
1.2认证
关键对象
Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;
Principal:身份信息
是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。
credential:凭证信息
是只有主体自己知道的安全信息,如密码、证书等。
1.3 授权
关键对象
授权可简单理解为who对what(which)进行How操作:
Who即主体(Subject),主体需要访问系统中的资源。
What即资源(Resource),如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。
How权限/许可(Permission),规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。
权限分为粗颗粒和细颗粒,粗颗粒权限是指对资源类型的权限,细颗粒权限是对资源实例的权限。
1.4访问控制
基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制。
基于资源的访问控制
RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制。
二、权限管理解决方案
2.1基于url拦截
基于url拦截是企业中常用的权限管理方法,实现思路是:将系统操作的每个url配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过Filter进行过虑,过虑器获取到用户访问的url,只要访问的url是用户分配角色中的url则放行继续访问。
如下图:
2.1.1 activeUser用户身份类
用户登陆成功记录activeUser信息并将activeUser存入session。

public class ActiveUser implements java.io.Serializable { private String userid;//用户id private String usercode;// 用户账号 private String username;// 用户名称 private List<SysPermission> menus;// 菜单 private List<SysPermission> permissions;// 权限
2.1.2anonymousURL.properties
anonymousURL.properties公开访问地址,无需身份认证即可访问。
2.1.3commonURL.properties
commonURL.properties公共访问地址,身份认证通过无需分配权限即可访问。
2.1.4用户身份认证拦截器
使用springmvc拦截器对用户身份认证进行拦截,如果用户没有登陆则跳转到登陆页面,本功能也可以使用filter实现 。

public class LoginInterceptor implements HandlerInterceptor { // 在进入controller方法之前执行 // 使用场景:比如身份认证校验拦截,用户权限拦截,如果拦截不放行,controller方法不再执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 校验用户访问是否是公开资源地址(无需认证即可访问) List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL"); // 用户访问的url String url = request.getRequestURI(); for (String open_url : open_urls) { if (url.indexOf(open_url) >= 0) { // 如果访问的是公开 地址则放行 return true; } } // 校验用户身份是否认证通过 HttpSession session = request.getSession(); ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser"); if (activeUser != null) { // 用户已经登陆认证,放行 return true; } // 跳转到登陆页面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; }
2.1.5 用户授权拦截器
使用springmvc拦截器对用户访问url进行拦截,如果用户访问的url没有分配权限则跳转到无权操作提示页面(refuse.jsp),本功能也可以使用filter实现。

public class PermissionInterceptor implements HandlerInterceptor { // 在进入controller方法之前执行 // 使用场景:比如身份认证校验拦截,用户权限拦截,如果拦截不放行,controller方法不再执行 // 进入action方法前要执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub // 用户访问地址: String url = request.getRequestURI(); // 校验用户访问是否是公开资源地址(无需认证即可访问) List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL"); // 用户访问的url for (String open_url : open_urls) { if (url.indexOf(open_url) >= 0) { // 如果访问的是公开 地址则放行 return true; } } //从 session获取用户公共访问地址(认证通过无需分配权限即可访问) List<String> common_urls = ResourcesUtil.gekeyList("commonURL"); // 用户访问的url for (String common_url : common_urls) { if (url.indexOf(common_url) >= 0) { // 如果访问的是公共地址则放行 return true; } } // 从session获取用户权限信息 HttpSession session = request.getSession(); ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser"); // 取出session中权限url // 获取用户操作权限 List<SysPermission> permission_list = activeUser.getPermissions(); // 校验用户访问地址是否在用户权限范围内 for (SysPermission sysPermission : permission_list) { String permission_url = sysPermission.getUrl(); if (url.contains(permission_url)) { return true; } } // 跳转到页面 request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward( request, response); return false; }
2.2用户登陆
用户输入用户账号和密码登陆,登陆成功将用户的身份信息(用户账号、密码、权限菜单、权限url等)记入activeUser类,并写入session。
2.2.1controller

//用户登陆提交 @RequestMapping("/loginsubmit") public String loginsubmit(HttpSession session,String usercode,String password,String randomcode) throws Exception{ //校验验证码 //从session获取正确的验证码 String validateCode = (String)session.getAttribute("validateCode"); if(!randomcode.equals(validateCode)){ //抛出异常:验证码错误 throw new CustomException("验证码 错误 !"); } //用户身份认证 ActiveUser activeUser = sysService.authenticat(usercode, password); //记录session session.setAttribute("activeUser", activeUser); return "redirect:first.action"; }
2.2.3 service接口

public ActiveUser authenticat(String usercode, String password) throws Exception; // 根据账号查询用户 public SysUser findSysuserByUsercode(String usercode) throws Exception; // 根据用户id获取权限 public List<SysPermission> findSysPermissionList(String userid) throws Exception; // 根据用户id获取菜单 public List<SysPermission> findMenuList(String userid) throws Exception;