您的位置:首页 > 其它

基于RBAC用户权限控制的校验

2017-03-18 14:13 309 查看
在上一次的文章中,简单的说明了基于RBAC用户权限控制的菜单显示和表结构的设计,而往往在企业项目中,仅仅控制用户菜单是不够的,而是要控制到每一个按钮,也就是每一个请求。

首先,用户权限校验的基本流程是,当用户登录成功后,将用户对应的权限存放在缓存中,用户每次发起一个请求时,在拦截器里面判断用户是否具有这个权限。

第一步:拦截器的配置

拦截器的配置是在spring-mvc.xml这个配置文件中的。

代码如下:

<!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller-->
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址 -->
<mvc:exclude-mapping path="/login.ding.jsp"/>
<mvc:exclude-mapping path="/login.pcding.jsp"/>
<mvc:exclude-mapping path="/login.index.jsp"/>
<mvc:exclude-mapping path="/user/toIndex"/>
<mvc:exclude-mapping path="/user/toLogin"/>
<mvc:exclude-mapping path="/www/login.jsp"/>
<bean class="com.siweisoft.interceptor.UserInfoLoginInterceptor"></bean>
</mvc:interceptor>
<!--<mvc:interceptor>-->
<!--<!– 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller–>-->
<!--<mvc:mapping path="/**" />-->
<!--<bean class="com.siweisoft.interceptor.LogInterceptor"></bean>-->
<!--</mvc:interceptor>-->
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller-->
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址 -->
<mvc:exclude-mapping path="/login.ding.jsp"/>
<mvc:exclude-mapping path="/login.pcding.jsp"/>
<mvc:exclude-mapping path="/login.index.jsp"/>
<mvc:exclude-mapping path="/user/toIndex"/>
<mvc:exclude-mapping path="/user/toLogin"/>
<mvc:exclude-mapping path="/www/login.jsp"/>
<bean class="com.siweisoft.interceptor.Interceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>


第二步:写一个缓存用于存放用户权限

Java中常用的缓存有memcache ,redis,
d0b4
ehcache ,这里使用一个本地的缓存类来实现一个简单的缓存。

代码如下:

/**
* 缓存管理类,待优化
* Created by Robin on 2017-01-16.
*/
public class CacheManager {
private static HashMap cacheMap = new HashMap();
private static CacheManager cacheManager=null;

//单实例构造方法
private CacheManager(){
super();
}

//    /**
//     * 获取缓存实例(单例)
//     * @return
//     */
//    public static CacheManager getCacheManager() {
//        if (cacheManager == null) {
//            cacheManager = new CacheManager();
//        }
//        return cacheManager;
//    }

/**
* 清除制定的缓存
* @param key 待清除缓存项的key
*/
public synchronized static void clearOnly(String key) {
cacheMap.remove(key);
}

//获取缓存信息
public static Object getCache(String key) {
if(key == null || "".equals(key)) {
throw new NullPointerException("待获取缓存对象的key为null");
}
return cacheMap.get(key);
}

//设置缓存
public static synchronized  boolean setCache(String key,Object object) {
if(key == null || "".equals(key)) {
throw new NullPointerException("待获取缓存对象的key为null");
}
if(hasCache(key)) {
throw new CacheManagerException("同名缓存已经存在!");
}
cacheMap.put(key,object);
return true;
}

//判断缓存key是否已经存在
public static boolean hasCache(String key) {
return cacheMap.containsKey(key);
}

//获取缓存的数目
public static int getCacheSize() {
return cacheMap.size();
}

//获取缓存对象中的所有键值名称
public static ArrayList getCacheAllkey() {
ArrayList a = new ArrayList();
try {
Iterator i = cacheMap.entrySet().iterator();
while (i.hasNext()) {
java.util.Map.Entry entry = (java.util.Map.Entry) i.next();
a.add((String) entry.getKey());
}
} catch (Exception ex) {} finally {
return a;
}
}

//清除所有缓存
public synchronized static void clearAll() {
cacheMap.clear();
}

public static void main(String[] args) {
CacheManager.setCache("1",1);
System.out.println("cache:"+ CacheManager.getCache("1"));

CacheManager.setCache("2",2);

System.out.println(CacheManager.getCache(""));
}
}


第三步:编写拦截器,对每一个请求进行校验

代码如下:

/**
* Created by Robin on 2017-3-10.
*/
public class RequestInterceptor implements HandlerInterceptor {

//boolean:表示是否需要将当前的请求拦截下来
//Object handler : 表示当前被拦截的请求的目标对象
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取当前的对象
User user = (User) request.getSession().getAttribute("user");
//当前请求的相对url
String requestUrl = request.getRequestURI();
//当前缓存中的URL
List<Map<String,Object>> list = (List<Map<String, Object>>) CacheManager.getCache("UserPer");
boolean statu = false;
if (list != null) {
for (int i = 0; i < list.size(); i++) {
String url = (String) list.get(i).get("permission_url");
statu |= requestUrl.equals(url);
}
}else{
statu = false;
}

//      判断是异步请求还是同步请求,如果是ajax请求响应头会有x-requested-with
String xrw  = request.getHeader("X-Requested-With");
if (!statu && xrw!=null){
response.setStatus(403);
}
//       同步请求
if (!statu && xrw == null) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().print("<script >alert('您没有此访问权限!');history.go(-1);</script>");
}
return statu;
}

//返回modelAndView之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}

//执行Handler完成执行此方法
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}


第四步:用户登录成功时,将用户权限存储在缓存类中

代码如下:

//   登录成功后跳转到首页
@RequestMapping(value="toIndex",method= RequestMethod.GET)
public String toIndex(int id,HttpServletRequest request) {
String url = "";
try {
User user = userService.selectByPrimaryKey(id);
if(user!=null&&!user.equals("")){
request.getSession().setAttribute("user",user);
//这里将用户的登录信息存储在缓存中
LoginUserCache.put(user,30*60);
//通过userID查当前用户的所有权限
List<Map<String,Object>> list = permissionService.findPermissionByUserId(id);
CacheManager.clearAll();
// 这里将用户的权限信息存储在缓存中
CacheManager.setCache("UserPer",list);
url = "../../swindex";
}else{
url = "../../index";
}
} catch (Exception e) {
e.printStackTrace();
}
return url;
}


这样,一个比较完善的用户权限控制就完成了,如有错误之处,还望及时指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: