用户越权访问的处理
一般来说,越权放问就好比你是非系统管理员用户,却偷偷的跑进了系统管理菜单,僭越权利访问里面的信息甚至修改其中的数据(不同级别的越权又称垂直越权访问),因此对数据的安全性造成极大的威胁,是故每家企业都有其方法来保证企业内部数据的安全性,也就是解决越权访问的问题。
有关改业务处理主要考虑下面两个方面:
url的越权访问和接口方法的越权访问
- 通过角色用户来判断是否越权访问
分下面几种情况来讨论:
a.当没有用户登录的时候:
只允许登录界面和一些js,css等非jsp/html的页面访问,这样算是越权
b.当用户登录了之后:
首先通过角色关系去数据库中查找他能够访问的页面,这样的话就可以针对能访问的做一个放行处理,非权限内的页面属于越权,这个时候拦截掉,可以直接让其跳转到登陆界面表示他越权了已经(自行处理越权后的操作)。
2.具体实现流程
统计好每个菜单url对应的接口方法和子页面访问路径(jsp或html等)
b.将统计好的数据一一对应起来,存放在配置文件中或者数据库某个表中,这些数据随着业务的新增或者裁剪应有相关对应的维护,暂时以配置文件为例
c.在登录模块中通过登录的用户角色查找它能够访问的菜单URL(写一个接口方法),存放在一个静态公有list变量中,如下定义:
public static List<String> MENU_URLS = new ArrayList<>();
将查询返回过来的url集合塞给MENU_URLS。
d,定义一个静态公有Properties变量,用来存放配置文件中的键值对,如下定义:
public static Properties MENU_INTERFACE = null;
然后对其进行读取配置文件并赋值
String url = request.getSession().getServletContext().getRealPath("/WEB-INF/classes/porturl.properties");
File file = new File(url);
try {
MENU_INTERFACE = new Properties();
FileInputStream inStream = new FileInputStream(file);
MENU_INTERFACE.load(inStream);
} catch (Exception e) {
System.out.println(e);
}
e.SpringMVC拦截器,判断session中用户是否过期,在doFilter 方法里匹配,只要js,css,pdf,png,jpg等文件可放行,在里面判断用户是否登录,没有登录的话只要是非登录页面的页面,统一视为越权访问。如果是已经登录的用户,我们可以取到登录后的MENU_URLS 和 MENU_INTERFACE 的信息,可以做如下判断:
如果访问的路径checkURL和MENU_URLS 中的任意子串能匹配的上的话说明是可以访问的,这种情况放行,否则拦截下来跳转登录,记录越权访问信息;
在上面的情况下,还会存在一种情况,当访问的路径是子页面的时候,这个时候需要去匹配,能匹配上的可以放行,这个需要通过checkURL去配置文件中找到对应的父URL,然后再进行匹配MENU_URLS,这个里面的父URL是唯一的,配置文件中一(父)对多(子)。
接口访问的也是同样的道理。
其中放行方法:
//正常访问,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
//初始化printWriterURL
String printWriterURL="<script>window.location.href='"+httpRequest.getContextPath()+ "/jsps/login/login.jsp';</script>";
//其他jsp的时候算是越权访问
logger.info("用户越权访问!!!!" + url);
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
这样就大功告成,具体代码细节如下所示:
public class SystemFilter implements Filter {
private static Logger logger = Logger.getLogger(SystemFilter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
HttpSession session = httpRequest.getSession(true);
String url = httpRequest.getRequestURI();
String printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp';</script>";
String checkURL = url;
if(checkURL.endsWith("/")){
checkURL = checkURL.substring(0, checkURL.length()-1);
if(checkURL.split("/").length == 2){
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
}
}
Object object = session.getAttribute("user");
User user = object == null ? null : (User) object;
boolean isAjaxRequest = false;
if (!StringUtils.isBlank(httpRequest.getHeader("x-requested-with"))
&& httpRequest.getHeader("x-requested-with").equals("XMLHttpRequest")) {
isAjaxRequest = true;
}
StringBuffer server = httpRequest.getRequestURL();
if (server.toString().contains(".css") || server.toString().contains(".jsp")
|| (server.toString().contains(".js") && !server.toString().contains(".jsp"))
|| server.toString().contains(".png") || server.toString().contains(".jpg") || server.toString().contains(".gif") || server.toString().contains(".svg")
|| server.toString().contains(".so") || server.toString().contains(".woff")
|| server.toString().contains(".ttf")
|| server.toString().endsWith("/downPDF") // 下载放行
|| server.toString().contains("/websocket") // 推送放行
){
if(user ==null && server.toString().contains(".jsp")){
if(server.toString().contains("index.jsp")){
logger.info("!!!用户未登录且使用index.jsp页面:" + url);
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
}else if(server.toString().contains("login.jsp")){
//当访问的是login.jsp的时候放行
filterChain.doFilter(servletRequest, servletResponse);
return;
}else{
//其他jsp的时候算是越权访问
logger.info("用户越权访问!!!!" + url);
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
}
}else if(user !=null && server.toString().contains(".jsp") && !(server.toString().contains("login.jsp"))){
Boolean ISURL = false;
//获取访问url的字符串
int urllen = checkURL.split("/").length;
String checkurl = "";
for(int i=2;i<urllen;i++){
if(i<urllen-1){
checkurl+=checkURL.split("/")[i]+"/";
}else{
checkurl+=checkURL.split("/")[i];
}
}
c:for(int j=0;j<LoginService.MENU_URLS.size();j++){
//获取角色用户对应二级菜单的URL
String _orUrls = LoginService.MENU_URLS.get(j);
if(_orUrls.equals(checkurl)){
System.out.println("符合条件的:"+checkurl);
ISURL = true;
break c;
}
}
//当上一个判断时不能访问考虑第二种情况
if(!ISURL){
//通过二级菜单读取配置文件中对应的子url,防止空指针异常
String purls = LoginService.MENU_INTERFACE.get(checkurl)==null?"":LoginService.MENU_INTERFACE.get(checkurl).toString();
d:for(int j=0;j<LoginService.MENU_URLS.size();j++){
String _orUrls = LoginService.MENU_URLS.get(j);
//获取角色用户对应二级菜单的URL和通过访问路径去查配置文件时候存在吻合则放行
if(_orUrls.equals(purls)){
System.out.println("符合条件的:"+purls);
ISURL = true;
break d;
}
}
}
if(!ISURL){
//越权访问
String msg = "ip=" + user.getIpaddr() + "&name=" + user.getUsername();
logger.info("!!!越权访问:" + url + ";用户信息:" + msg);
printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp?" + msg + "';</script>";
}else{
System.out.println("========>"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
//正常访问,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
}
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
}
// 如果发现是css或者js文件,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
}
if (!isAjaxRequest) {
if (user != null && (server.toString().contains("index.jsp") || server.toString().contains("login.jsp"))) {
// 如果发现是css或者js文件,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
} else {
if(user != null){
System.out.println("-----------1-----------"+checkURL);
if(LoginService.MENU_INTERFACE != null && LoginService.MENU_INTERFACE.size() != 0
&& LoginService.MENU_URLS != null && LoginService.MENU_URLS.size() != 0 ){
if(checkURL.split("/").length == 4){
System.out.println("-----------2-----------"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
// if(LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]) == null){
// // 如果发现是css或者js文件,直接放行
// filterChain.doFilter(servletRequest, servletResponse);
// return;
// }
Boolean hasIn = false;
if(null != LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3])){
String[] urls = LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]).toString().split(",");
// jsp/pages/configmgt/device/deviceList.jsp,jsp/pages/configmgt/systemmgt/systemmgtList.jsp
a:for(int i=0;i<urls.length;i++){
String _url = urls[i];
for(int j=0;j<LoginService.MENU_URLS.size();j++){
String _orUrls = LoginService.MENU_URLS.get(j);
if(_orUrls.equals(_url)){
System.out.println("符合条件的:"+_url);
hasIn = true;
break a;
}
}
}
}
if(!hasIn){
//越权访问
String msg = "ip=" + user.getIpaddr() + "&name=" + user.getUsername();
logger.info("!!!越权访问:" + url + ";用户信息:" + msg);
printWriterURL = "<script>window.location.href='" + httpRequest.getContextPath() + "/jsps/login/login.jsp?" + msg + "';</script>";
}else{
System.out.println("========>"+LoginService.MENU_INTERFACE.get(checkURL.split("/")[2]+"/"+checkURL.split("/")[3]));
//正常访问,直接放行
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}
}
}
PrintWriter p = httpResponse.getWriter();
p.write(printWriterURL);
p.flush();
p.close();
return;
}
}
if (url.toString().contains(".jsp")) {
logger.info(httpRequest.getSession().getServletContext().getRealPath("/") + "-------");
logger.info("拦截器放行地址:-------------------" + url);
}
filterChain.doFilter(servletRequest, servletResponse);
return;
}
/**
* 判断是否为Ajax请求
*
* @param request
* HttpServletRequest
* @return 是true, 否false
*/
public static boolean isAjaxRequest(HttpServletRequest request) {
return request.getRequestURI().startsWith("/api");
// String requestType = request.getHeader("X-Requested-With");
// return requestType != null && requestType.equals("XMLHttpRequest");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
// To change body of implemented methods use File | Settings | File
// Templates.
}
}