Browse Source

安全漏洞修复,添加权限验证

LAPTOP-KB9HII50\70708 2 years ago
parent
commit
ad1087b7e3

+ 12 - 0
svr/svr-iot/src/main/java/com/yihu/iot/config/MvcConfig.java

@ -3,6 +3,7 @@ package com.yihu.iot.config;
import com.yihu.iot.interceptor.CrosXssFilter;
import com.yihu.iot.interceptor.GateWayInterceptor;
import com.yihu.iot.interceptor.PermissionInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -21,6 +22,8 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
    private Logger logger = LoggerFactory.getLogger(MvcConfig.class);
    @Autowired
    private GateWayInterceptor gateWayInterceptor;
    @Autowired
    private PermissionInterceptor permissionInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
@ -31,6 +34,15 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
                "/svr-iot/open/gc/accesstoken",
                "/svr-iot/open/gc/createGcClientDetails");
        registry.addInterceptor(permissionInterceptor)
                .addPathPatterns("/svr-iot/**")
                .addPathPatterns("/equipmentManage/**")
                .excludePathPatterns(
                "/svr-iot/open/gc/**","/svr-iot/systemDict/findDictByCode"
                        ,"/svr-iot/systemDict/findByDictName","svr-iot/fileUpload/open/fileUpload"
        );
        super.addInterceptors(registry);
        logger.info("init gateWayInterceptor");
    }

+ 55 - 0
svr/svr-iot/src/main/java/com/yihu/iot/controller/common/CommonController.java

@ -0,0 +1,55 @@
package com.yihu.iot.controller.common;
import com.yihu.iot.dao.common.BaseMenuUrlDao;
import com.yihu.jw.entity.base.login.BaseLoginLogDO;
import com.yihu.jw.entity.base.menu.BaseMenuUrlDO;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.*;
/**
 * Created by yeshijie on 2022/7/20.
 */
@RestController
@RequestMapping("open/test")
@Api(tags = "通用自测相关操作", description = "通用自测相关操作")
public class CommonController extends BaseController{
    @Autowired
    WebApplicationContext applicationContext;
    @Autowired
    private BaseMenuUrlDao baseMenuUrlDao;
    @GetMapping("getAllUrl")
    public List<String> getAllUrl(){
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        //获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        List<String> urlList = new ArrayList<>();
        for (RequestMappingInfo info : map.keySet()){
            //获取url的Set集合,一个方法可能对应多个url
            Set<String> patterns = info.getPatternsCondition().getPatterns();
            for (String url : patterns) {
                if(url.contains("/open/")||url.contains("/swagger-resources")
                        ||url.contains("/error")||url.contains("/svr-iot/analyze/")){
                    continue;
                }
                urlList.add(url);
                BaseMenuUrlDO urlDO = new BaseMenuUrlDO();
                urlDO.setCreateTime(new Date());
                urlDO.setUrl(url);
                baseMenuUrlDao.save(urlDO);
            }
        }
        return urlList;
    }
}

+ 21 - 0
svr/svr-iot/src/main/java/com/yihu/iot/dao/common/BaseLoginLogDao.java

@ -0,0 +1,21 @@
package com.yihu.iot.dao.common;
import com.yihu.jw.entity.base.login.BaseLoginLogDO;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
public interface BaseLoginLogDao extends PagingAndSortingRepository<BaseLoginLogDO, String>, JpaSpecificationExecutor<BaseLoginLogDO> {
    @Query("from BaseLoginLogDO l where l.openid=?1 order by l.createTime desc")
    List<BaseLoginLogDO> findByOpenId(String openid);
    @Query("from BaseLoginLogDO l where l.userId=?1 order by l.createTime desc")
    List<BaseLoginLogDO> findByUserId(String openid);
    @Query(value = "SELECT a.* from base_login_log a WHERE a.token=?1 ORDER BY a.create_time desc LIMIT 1",nativeQuery = true)
    BaseLoginLogDO findByToken(String token);
}

+ 12 - 0
svr/svr-iot/src/main/java/com/yihu/iot/dao/common/BaseMenuUrlDao.java

@ -0,0 +1,12 @@
package com.yihu.iot.dao.common;
import com.yihu.jw.entity.base.menu.BaseMenuUrlDO;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
 * Created by yeshijie on 2022/7/20.
 */
public interface BaseMenuUrlDao extends PagingAndSortingRepository<BaseMenuUrlDO, String>, JpaSpecificationExecutor<BaseMenuUrlDO> {
}

+ 72 - 0
svr/svr-iot/src/main/java/com/yihu/iot/interceptor/PermissionInterceptor.java

@ -0,0 +1,72 @@
package com.yihu.iot.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.yihu.iot.service.common.PermissionService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
 * 菜单权限校验
 *
 * @author George
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    private Logger logger = LoggerFactory.getLogger(PermissionInterceptor.class);
    public static String status = "1";
    @Autowired
    public PermissionService permissionService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag = true;
        try {
            request.setCharacterEncoding("UTF-8");
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            request.setAttribute("log-start", new Date().getTime());
            response.setCharacterEncoding("UTF-8");
            String uri = request.getRequestURI();
            logger.info("getRequestURI"+uri);
            //越权验证
            if(!permissionService.isPermission(uri)){
                JSONObject json = new JSONObject();
                json.put("status",403);
                json.put("message","该操作没有权限");
                response.getOutputStream().write(json.toString().getBytes("UTF-8"));
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

+ 123 - 0
svr/svr-iot/src/main/java/com/yihu/iot/service/common/PermissionService.java

@ -0,0 +1,123 @@
package com.yihu.iot.service.common;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yihu.iot.dao.common.BaseLoginLogDao;
import com.yihu.jw.entity.base.login.BaseLoginLogDO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
 * Created by yeshijie on 2022/3/14.
 */
@Service
public class PermissionService {
    private static final Logger logger = LoggerFactory.getLogger(PermissionService.class);
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private BaseLoginLogDao baseLoginLogDao;
    @Value("${spring.profiles}")
    private String profiles;
    /**
     * 判断用户是否有权限
     */
    public boolean isPermission(String url){
        try {
            String uid = getUID();
            //            String uid = "402803f9658455110165845b84850000";
            logger.info("uid:" + uid);
            if(StringUtils.isBlank(uid)){
                return true;
            }
            //判断是否开启权限校验 未设置或者为0则不开启权限校验
            String sql = " select code from iot_system_dict where dict_name ='isPermission'  ";
            List<String> isPermissions = jdbcTemplate.queryForList(sql,String.class);
            if(isPermissions.size()==0||"0".equals(isPermissions.get(0))){
                return true;
            }
            if ("2c9a80ed72068fa20172164d756c000c".equals(uid)||"402803f9658455110165845b84850000".equals(uid)) {
                //管理员 admxin 和 测试管理员 18800000001
                return true;
            }
            String usrSql = "SELECT role_id from "+getDbName()+".base_user where id=?";
            List<String> roleIds = jdbcTemplate.queryForList(usrSql,new Object[]{uid},String.class);
            if(roleIds.size()==0){
                return false;
            }
            String roleId = roleIds.get(0);
            if("company".equals(roleId)||"platform".equals(roleId)){
                //新申请的厂商和平台商才做权限校验
                String db = getDbName();
                String sqlCount = "SELECT count(DISTINCT mu.url) from "+db+".base_menu m,"+db+".base_role_menu rm,"+db+".base_menu_url mu " +
                        "WHERE rm.role_id = '"+roleId+"'  and m.id = rm.menu_id and m.status=1 " +
                        "and m.id = mu.menu_id and mu.url='"+url+"'";
                Integer num = jdbcTemplate.queryForObject(sqlCount,Integer.class);
                if(num==0){
                    return false;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }
    public String getUID(){
        BaseLoginLogDO loginLogDO = getLoginLog();
        if(loginLogDO != null){
            return loginLogDO.getUserId();
        }
        return null;
    }
    private BaseLoginLogDO getLoginLog(){
        String accessToken = this.extractToken(getRequest());
        String sql = "select * from "+getDbName()+".base_login_log a WHERE a.token=? ORDER BY a.create_time desc LIMIT 1";
        logger.info("sql+"+sql);
        List<BaseLoginLogDO> list = jdbcTemplate.query(sql,new Object[]{accessToken},new BeanPropertyRowMapper<>(BaseLoginLogDO.class));
        if(list!=null&&list.size()>0){
            return list.get(0);
        }
        return null;
    }
    public String getDbName(){
        String db = "base";
        if("iotprod".equals(profiles)){
            db = "`iot-base`";
        }
        return db;
    }
    private String extractToken(HttpServletRequest request) {
        String accessToken = request.getHeader("token");
        if (null == accessToken) {
            accessToken = request.getParameter("token");
        }
        return accessToken;
    }
    public HttpServletRequest getRequest(){
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }
}

+ 4 - 1
svr/svr-iot/src/main/resources/application.yml

@ -22,7 +22,10 @@ spring:
      test-while-idle: true #指明连接是否被空闲连接回收器(如果有)进行检验,如果检测失败,则连接将被从池中去除
      min-evictable-idle-time-millis: 3600000 #连接池中连接,在时间段内一直空闲,被逐出连接池的时间(1000*60*60),以毫秒为单位
      time-between-eviction-runs-millis: 300000 #在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位,一般比minEvictableIdleTimeMillis小
  http:
    multipart:
      max-file-size: 50MB
      max-request-size: 100MB
  data:
    elasticsearch: #ElasticsearchProperties
      cluster-name: jkzl #默认即为elasticsearch  集群名