说明
这里仅讨论 同一个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 中保存的用户id
LOGGER.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中的配置