该过滤器的功能是对权限不足的用户的不合理访问做拦截,处理方式是通过给页面的url添加权限,用户本身也会被绑定权限,当用户的权限包含需访问页面的权限时则可访问,否则将被拦截。以下是实现思路:
1.首先过滤掉不需要被拦截的资源,包括图片,js,css等一些静态资源:
//不拦截某些资源
if (canIgnore(request)) {
filterChain.doFilter(request, response);
return;
}
private boolean canIgnore(HttpServletRequest request) {
String url = request.getRequestURI();
//首次登录不被拦截
if(url.equals("****")){
return true;
}
for (String ignore : prefixIignores) {
if (url.startsWith(ignore)) {
return true;
}
}
return false;
}
2.判断用户是否为登录状态,用户登录后是存放在session中的,判断如下:
UserEntity user = (UserEntity) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "请先登录!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
3.拿到用户访问页面的uri,然后将该uri与需要权限的uri列表中的uri对比,若为null则说明该uri不需要被拦截:
final String uri = request.getRequestURI();
try {
resourceEntity = service.findResourceByUri(uri);
} catch (ServiceException e1) {
e1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if(resourceEntity == null){
filterChain.doFilter(request, response);
return;
}
4.如果不为null,拿到该uri所需的权限并判断用户是否有权限访问该uri:
PrivilegeEntity required_Privilege = resourceEntity.getPrivilege();
UserEntity userEntity = service.findUser(user.getId());
Set<PrivilegeEntity> list = null;
try {
list = service.getUserAllPrivilege(user.getId());
} catch (DbAgentException | ServiceException e) {
e.printStackTrace();
}
if (!list.contains(required_Privilege)) {
// 没有权限,则提示用户权限不足
request.setAttribute("message", "对不起,您没有权限");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
// 如果有,则不拦截
filterChain.doFilter(request, response);
以上就是过滤器的思路,一路走下来思路完全没问题,也实现了功能,但是随着数据量增大,发现进入页面时速度特别慢,于是思考是什么导致了读取速度过慢的问题。然后,就发现了问题:
从贴出的代码可以看出,每次拦截与数据库进行了4次交互,在数据量变大时,这4次的交互所需时间是不可忽略的!解决思路:
思考之后发现:用户拥有的权限在本次访问中是不会有变化的,而存放于资源库中需要权限才能访问的uri在当次访问中也是不会变化的。所以,在第一次登陆获取到用户的权限和所有需要权限访问的资源uri时,将其存入session中,在第一次登录之后,之后的操作与之前相比减少了一半与数据库交互的次数,访问速率也得到了不错的提升:
request.getSession().setAttribute("privilege", list);
request.getSession().setAttribute("uriList", uriList);