说明
这里仅讨论 同一个tomcat,部署了两个工程(两个war包)。不涉及不同tomcat,不涉及集群
背景
tomcat中的工程A包含用户登录、退出、权限控制等功能;工程B包含业务功能接口。工程A将用户登录信息加密响应给前端,前端在请求工程B时将用户加密信息放入请求header,工程B解密获得用户信息。
这种方式在安全扫描中提示存在垂直越权问题。即低权限的用户如果拿到高权限用户的加密信息,就可以拿到高权限用户的数据
修复:
将用户信息存在session中
步骤1
服务器tomcat安装目录,conf文件夹下,sever.xml 文件标签新增配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"><Context path="/biz-m-rest" reloadable="true" crossContext="true" sessionCookiePath="/" /><Context path="/mams-rest" reloadable="true" crossContext="true" sessionCookiePath="/" /></Host>
开启biz-m-rest、mams-rest服务session共享,sessionCookiePath=“/” 配置很重要,没有该配置 两个工程中打印的sessionId 不同
步骤2
工程A登录接口封装方法,将用户信息存入session中,sessionId 为key
网上很多博客用固定的key(session字符串),固定key虽然实现session共享,但是没有解决安全问题。本方法使用动态 sessionId 作为key
/*
*regUser参数为用户登录后,查询数据库封装的当前用户信息
*/
private void setUserInfoSissioin(SysRegisterUser regUser,HttpServletRequest request){HttpSession httpSession = request.getSession();String sessionId = httpSession.getId();logger.info("当前session id是=============:"+sessionId);Object jsonRegUser = JSON.toJSON(regUser);httpSession.setAttribute("user",jsonRegUser);ServletContext context = httpSession.getServletContext();context.setAttribute(sessionId, httpSession);}
步骤3
工程B中通过sessionId 获得用户信息
/**通过session 中保存的用户信息,和crctoken中解密的用户id 比较,相同返回true;否则返回false**/public Boolean isLoginUser(HttpServletRequest httpServletRequest){Boolean bool = false;String crcTokenUserId = getLoginUserId(); //cookie中解密的用户id(不安全)try {HttpServletRequest request = getRequest();String sessionId = request.getSession().getId();LOGGER.info("====biz_service session=====================start==="+sessionId);ServletContext Context = request.getServletContext();ServletContext Context1= Context.getContext("/mams-rest"); //共享session,和tomcat sever.xml 中配置一致if(Context1 !=null && !Context1.equals("")){HttpSession sess=(HttpSession)Context1.getAttribute(sessionId);if(sess.getAttribute("user")!=null){JSONObject jsonObject = new JSONObject().parseObject(sess.getAttribute("user").toString());String sessionUserId = jsonObject.getString("userId"); //session 中保存的用户idLOGGER.info("tomcat 共享session 测试=====================start====sessionUserId=002==="+sessionUserId);if(StringUtils.isNotBlank(sessionUserId)&&StringUtils.isNotBlank(crcTokenUserId)&&crcTokenUserId.equals(sessionUserId)){bool = true;}}}}catch (Exception e){//报错说明用户还没登录,拿不到session信息LOGGER.error("=============请先登录==========");e.printStackTrace();}return bool;}
测试:
工程A打印的sessionId
工程B打印的sessionId
动态获取工程A和工程B的sessionId,id相同,工程B才可以正确获取工程A中存的用户信息
保证工程A和工程B 有相同的sessionId 依赖 tomcat sever.xml中的配置