JFinal-layuiv1.4.2 来袭,XSS,CSRF防御,程序器

  • Post author:
  • Post category:其他


感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18436.html



前言

JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会前端layui,也能轻松掌握使用。


JFinal-layui v1.4.2 新增XSS、CSRF防御和代码生成器,加强web安全和提升开发效率!在工作中发现,一些公司在给客户开发系统的时候,都很容易忽略了web安全的内容,或者根本不考虑web安全漏洞,所以这样开发出来的系统本身就是存在很大的安全隐患,只要稍微有点技术的人员就能进行XSS攻击和CSRF跨站请求伪造!因为本人有过一段难忘的web安全漏洞修复的经历,所以把积累的一些经验应用到JFinal-layui中,让系统更加安全可靠!

v1.4.2更新内容详情:


一、XSS攻击防御


JFinal-layui主要是对XSS的存储型攻击进行防御,把用户输入的数据都进行XSS过滤,避免对系统造成不良影响。利用JFInal的Handler来实现,重写HttpServletRequestWrapper非常简单。


1、自定义XssHttpServletRequestWrapper类,重写getParameter:

/**  
 * xss过滤处理  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{  
	  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
   
    /**  
     * 重写并过滤getParameter方法  
     */  
    @Override  
    public String getParameter(String name) {  
        return getBasicHtmlandimage(super.getParameter(name));  
          
    }  
       
    /**  
     * 重写并过滤getParameterValues方法  
     */  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if (null == values){  
            return null;  
        }  
        for (int i = 0; i < values.length; i++) {  
            values[i] = getBasicHtmlandimage(values[i]);  
        }  
        return values;  
    }  
       
    /**  
     * 重写并过滤getParameterMap方法  
     */  
    @Override  
    public Map<String,String[]> getParameterMap() {  
		Map<String,String[]> paraMap = super.getParameterMap();  
        // 对于paraMap为空的直接return  
        if (null == paraMap || paraMap.isEmpty()) {  
            return paraMap;  
        }  
          
        //super.getParameterMap()不允许任何修改,所以只能做深拷贝  
        Map<String, String[]> paraMapCopy = new HashMap<String, String[]>();  
        //实际上putAll只对基本类型深拷贝有效,如果是自定义类型,则要找其他办法  
        paraMapCopy.putAll(paraMap);  
          
        for (Map.Entry<String, String[]> entry : paraMapCopy.entrySet()) {  
            String[] values     = entry.getValue();  
            if (null == values) {  
                continue;  
            }  
            String[] newValues  = new String[values.length];  
            for (int i = 0; i < values.length; i++) {  
                newValues[i] = getBasicHtmlandimage(values[i]);  
            }  
            entry.setValue(newValues);  
        }  
        return paraMapCopy;  
    }  
      
    private static String getBasicHtmlandimage(String html) {  
	    if (html == null)  
	        return null;  
	    return Jsoup.clean(html, Whitelist.basicWithImages());  
	}  
}  

2、新建XssHandler拦截器:

/**  
 * xss拦截器  
 * @author QinHaiLin  
 *  
 */  
public class XssHandler extends Handler {  
  
  
	// 排除的url,使用的target.startsWith匹配的  
   private String excludePattern;  
      
   /**  
    * 忽略列表,使用正则排除url  
    * @param exclude  
    */  
   public XssHandler(String excludePattern) {  
       this.excludePattern = excludePattern;  
   }  
  
	@Override  
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {  
  
		java.util.regex.Pattern pattern = Pattern.compile(excludePattern);  
		//带.表示非action请求,忽略(其实不太严谨,如果是伪静态,比如.html会被错误地排除);匹配excludePattern的,忽略  
       if (target.indexOf(".") == -1 && !(!StringUtil.isBlank(excludePattern) && pattern.matcher(target).find() ) ){  
           request = new XssHttpServletRequestWrapper(request);  
       }  
         
       next.handle(target, request, response, isHandled);  
         
	}  
  
}  

3、在MainConfig里面配置XssHandler拦截器,那么对XSS的存储型攻击就可以进行有效的防御了。

 /**  
	 * 配置全局处理器  
	 */  
	@Override  
	public void configHandler(Handlers me) {  
		/** 配置druid监控 **/  
		me.add(DruidKit.getDruidStatViewHandler());   
		// 路由处理  
		me.add(new CommonHandler());  
		// XSS过滤  
		me.add(new XssHandler("^\\/portal/form/view.*"));  
	}


二、CSRF跨站请求伪造防御


针对CSRF跨站请求伪造,JFinal-layui主要是对添加、修改的业务表单加入token验证机制,这样就可以解决重要业务操作的安全性。我们的拦截是全局验证拦截,在开发功能过程中就是顺手做的事情,简单高效。

1、利用JFinal的token机制,创建自己的TokenService:

/**  
 * token  
 * @author QinHaiLin  
 * @date 2020-02-14  
 */  
public class TokenService {  
  
	/**  
	 * 创建token  
	 * @param c  
	 */  
	public void createToken(Controller c){  
		TokenManager.createToken(c, Const.DEFAULT_TOKEN_NAME, Const.DEFAULT_SECONDS_OF_TOKEN_TIME_OUT);  
	}  
	  
	/**  
	 * 验证token  
	 * @param c  
	 */  
	public boolean validateToken(Controller c){  
		return TokenManager.validateToken(c, Const.DEFAULT_TOKEN_NAME);  
	}  
}  

2、再创建TokenInterceptor的拦截器进行全局拦截验证:

/**  
 * token拦截器  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class TokenInterceptor implements Interceptor {  
  
	@Inject  
	TokenService tokenService;  
	  
	@Override  
	public void intercept(Invocation inv) {  
		Controller c=inv.getController();  
		String methName=inv.getMethod().getName();  
		  
		//给默认的添加、修改方法添加token  
		if(methName.equals("add")||methName.equals("edit")){  
			tokenService.createToken(c);		  
		}  
		  
		//验证token  
		if(methName.equals("save")||methName.equals("update")){  
			boolean b=tokenService.validateToken(c);  
			if(!b){  
				boolean isAjax="XMLHttpRequest".equalsIgnoreCase(c.getHeader("X-Requested-With"));  
				if(isAjax){  
					c.renderJson(Ret.fail("msg", "token验证不通过,请刷新页面"));  
				}else{  
					c.setAttr("msg", "token验证不通过");  
					c.renderError(403);  
				}  
				return;  
			}  
			//添加修改成功后,返回对的页面,此处是解决业务验证不通过的情况,如:添加用户时,如果存在用户编号,那么需要重新填写,此时就要重新赋值新的token  
			tokenService.createToken(c);  
		}  
		inv.invoke();  
	}  
  
}  

3、在MainConfig配置成全局拦截器即可:

/**  
	 * 配置全局拦截器  
	 */  
	@Override  
	public void configInterceptor(Interceptors me) {  
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());  
		me.addGlobalActionInterceptor(new SessionInterceptor());  
		me.addGlobalActionInterceptor(new ExceptionInterceptor());  
		//表单token验证拦截器  
		me.addGlobalActionInterceptor(new TokenInterceptor());  
		me.addGlobalActionInterceptor(new LoggerInterceptor());  
	}  

4、在添加修改的操作表单输出token:#(token)

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器


三、代码生成器


为满足广大用户要求,还是决定把代码生成器集成进来,那么有了这一神器,就可以把那些繁琐重复的开发工作交给代码器了,一键多表生成代码文件,页面操作简单,直接生成代码文件到项目当中,刷新重启项目即可。


1、代码生成器操作页面,选择需要的表,可多选,点击选择按钮即可:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

2、点击生成代码,这是预览代码,还没有真正创建代码文件,点击下载代码才是最终在项目中创建:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

3、点击下载代码,创建文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

4、刷新项目,就能在预先设置的package里面创建对应的Java文件了,html目录也是按照相应规则创建对应的目录:

java文件: html文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

5、此时代码文件已经创建好了,还需要最关键的一步,那就是把_MappingKit.java里面在数据库表映射关系配置到主配置文件中:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

6、最后就是启动项目,配置菜单权限即可访问了。

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器
感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18436.html



前言

JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会前端layui,也能轻松掌握使用。


JFinal-layui v1.4.2 新增XSS、CSRF防御和代码生成器,加强web安全和提升开发效率!在工作中发现,一些公司在给客户开发系统的时候,都很容易忽略了web安全的内容,或者根本不考虑web安全漏洞,所以这样开发出来的系统本身就是存在很大的安全隐患,只要稍微有点技术的人员就能进行XSS攻击和CSRF跨站请求伪造!因为本人有过一段难忘的web安全漏洞修复的经历,所以把积累的一些经验应用到JFinal-layui中,让系统更加安全可靠!

v1.4.2更新内容详情:


一、XSS攻击防御


JFinal-layui主要是对XSS的存储型攻击进行防御,把用户输入的数据都进行XSS过滤,避免对系统造成不良影响。利用JFInal的Handler来实现,重写HttpServletRequestWrapper非常简单。


1、自定义XssHttpServletRequestWrapper类,重写getParameter:

/**  
 * xss过滤处理  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{  
	  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
   
    /**  
     * 重写并过滤getParameter方法  
     */  
    @Override  
    public String getParameter(String name) {  
        return getBasicHtmlandimage(super.getParameter(name));  
          
    }  
       
    /**  
     * 重写并过滤getParameterValues方法  
     */  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if (null == values){  
            return null;  
        }  
        for (int i = 0; i < values.length; i++) {  
            values[i] = getBasicHtmlandimage(values[i]);  
        }  
        return values;  
    }  
       
    /**  
     * 重写并过滤getParameterMap方法  
     */  
    @Override  
    public Map<String,String[]> getParameterMap() {  
		Map<String,String[]> paraMap = super.getParameterMap();  
        // 对于paraMap为空的直接return  
        if (null == paraMap || paraMap.isEmpty()) {  
            return paraMap;  
        }  
          
        //super.getParameterMap()不允许任何修改,所以只能做深拷贝  
        Map<String, String[]> paraMapCopy = new HashMap<String, String[]>();  
        //实际上putAll只对基本类型深拷贝有效,如果是自定义类型,则要找其他办法  
        paraMapCopy.putAll(paraMap);  
          
        for (Map.Entry<String, String[]> entry : paraMapCopy.entrySet()) {  
            String[] values     = entry.getValue();  
            if (null == values) {  
                continue;  
            }  
            String[] newValues  = new String[values.length];  
            for (int i = 0; i < values.length; i++) {  
                newValues[i] = getBasicHtmlandimage(values[i]);  
            }  
            entry.setValue(newValues);  
        }  
        return paraMapCopy;  
    }  
      
    private static String getBasicHtmlandimage(String html) {  
	    if (html == null)  
	        return null;  
	    return Jsoup.clean(html, Whitelist.basicWithImages());  
	}  
}  

2、新建XssHandler拦截器:

/**  
 * xss拦截器  
 * @author QinHaiLin  
 *  
 */  
public class XssHandler extends Handler {  
  
  
	// 排除的url,使用的target.startsWith匹配的  
   private String excludePattern;  
      
   /**  
    * 忽略列表,使用正则排除url  
    * @param exclude  
    */  
   public XssHandler(String excludePattern) {  
       this.excludePattern = excludePattern;  
   }  
  
	@Override  
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {  
  
		java.util.regex.Pattern pattern = Pattern.compile(excludePattern);  
		//带.表示非action请求,忽略(其实不太严谨,如果是伪静态,比如.html会被错误地排除);匹配excludePattern的,忽略  
       if (target.indexOf(".") == -1 && !(!StringUtil.isBlank(excludePattern) && pattern.matcher(target).find() ) ){  
           request = new XssHttpServletRequestWrapper(request);  
       }  
         
       next.handle(target, request, response, isHandled);  
         
	}  
  
}  

3、在MainConfig里面配置XssHandler拦截器,那么对XSS的存储型攻击就可以进行有效的防御了。

 /**  
	 * 配置全局处理器  
	 */  
	@Override  
	public void configHandler(Handlers me) {  
		/** 配置druid监控 **/  
		me.add(DruidKit.getDruidStatViewHandler());   
		// 路由处理  
		me.add(new CommonHandler());  
		// XSS过滤  
		me.add(new XssHandler("^\\/portal/form/view.*"));  
	}


二、CSRF跨站请求伪造防御


针对CSRF跨站请求伪造,JFinal-layui主要是对添加、修改的业务表单加入token验证机制,这样就可以解决重要业务操作的安全性。我们的拦截是全局验证拦截,在开发功能过程中就是顺手做的事情,简单高效。

1、利用JFinal的token机制,创建自己的TokenService:

/**  
 * token  
 * @author QinHaiLin  
 * @date 2020-02-14  
 */  
public class TokenService {  
  
	/**  
	 * 创建token  
	 * @param c  
	 */  
	public void createToken(Controller c){  
		TokenManager.createToken(c, Const.DEFAULT_TOKEN_NAME, Const.DEFAULT_SECONDS_OF_TOKEN_TIME_OUT);  
	}  
	  
	/**  
	 * 验证token  
	 * @param c  
	 */  
	public boolean validateToken(Controller c){  
		return TokenManager.validateToken(c, Const.DEFAULT_TOKEN_NAME);  
	}  
}  

2、再创建TokenInterceptor的拦截器进行全局拦截验证:

/**  
 * token拦截器  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class TokenInterceptor implements Interceptor {  
  
	@Inject  
	TokenService tokenService;  
	  
	@Override  
	public void intercept(Invocation inv) {  
		Controller c=inv.getController();  
		String methName=inv.getMethod().getName();  
		  
		//给默认的添加、修改方法添加token  
		if(methName.equals("add")||methName.equals("edit")){  
			tokenService.createToken(c);		  
		}  
		  
		//验证token  
		if(methName.equals("save")||methName.equals("update")){  
			boolean b=tokenService.validateToken(c);  
			if(!b){  
				boolean isAjax="XMLHttpRequest".equalsIgnoreCase(c.getHeader("X-Requested-With"));  
				if(isAjax){  
					c.renderJson(Ret.fail("msg", "token验证不通过,请刷新页面"));  
				}else{  
					c.setAttr("msg", "token验证不通过");  
					c.renderError(403);  
				}  
				return;  
			}  
			//添加修改成功后,返回对的页面,此处是解决业务验证不通过的情况,如:添加用户时,如果存在用户编号,那么需要重新填写,此时就要重新赋值新的token  
			tokenService.createToken(c);  
		}  
		inv.invoke();  
	}  
  
}  

3、在MainConfig配置成全局拦截器即可:

/**  
	 * 配置全局拦截器  
	 */  
	@Override  
	public void configInterceptor(Interceptors me) {  
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());  
		me.addGlobalActionInterceptor(new SessionInterceptor());  
		me.addGlobalActionInterceptor(new ExceptionInterceptor());  
		//表单token验证拦截器  
		me.addGlobalActionInterceptor(new TokenInterceptor());  
		me.addGlobalActionInterceptor(new LoggerInterceptor());  
	}  

4、在添加修改的操作表单输出token:#(token)

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器


三、代码生成器


为满足广大用户要求,还是决定把代码生成器集成进来,那么有了这一神器,就可以把那些繁琐重复的开发工作交给代码器了,一键多表生成代码文件,页面操作简单,直接生成代码文件到项目当中,刷新重启项目即可。


1、代码生成器操作页面,选择需要的表,可多选,点击选择按钮即可:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

2、点击生成代码,这是预览代码,还没有真正创建代码文件,点击下载代码才是最终在项目中创建:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

3、点击下载代码,创建文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

4、刷新项目,就能在预先设置的package里面创建对应的Java文件了,html目录也是按照相应规则创建对应的目录:

java文件: html文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

5、此时代码文件已经创建好了,还需要最关键的一步,那就是把_MappingKit.java里面在数据库表映射关系配置到主配置文件中:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

6、最后就是启动项目,配置菜单权限即可访问了。

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器
感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18436.html



前言

JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会前端layui,也能轻松掌握使用。


JFinal-layui v1.4.2 新增XSS、CSRF防御和代码生成器,加强web安全和提升开发效率!在工作中发现,一些公司在给客户开发系统的时候,都很容易忽略了web安全的内容,或者根本不考虑web安全漏洞,所以这样开发出来的系统本身就是存在很大的安全隐患,只要稍微有点技术的人员就能进行XSS攻击和CSRF跨站请求伪造!因为本人有过一段难忘的web安全漏洞修复的经历,所以把积累的一些经验应用到JFinal-layui中,让系统更加安全可靠!

v1.4.2更新内容详情:


一、XSS攻击防御


JFinal-layui主要是对XSS的存储型攻击进行防御,把用户输入的数据都进行XSS过滤,避免对系统造成不良影响。利用JFInal的Handler来实现,重写HttpServletRequestWrapper非常简单。


1、自定义XssHttpServletRequestWrapper类,重写getParameter:

/**  
 * xss过滤处理  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{  
	  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
   
    /**  
     * 重写并过滤getParameter方法  
     */  
    @Override  
    public String getParameter(String name) {  
        return getBasicHtmlandimage(super.getParameter(name));  
          
    }  
       
    /**  
     * 重写并过滤getParameterValues方法  
     */  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if (null == values){  
            return null;  
        }  
        for (int i = 0; i < values.length; i++) {  
            values[i] = getBasicHtmlandimage(values[i]);  
        }  
        return values;  
    }  
       
    /**  
     * 重写并过滤getParameterMap方法  
     */  
    @Override  
    public Map<String,String[]> getParameterMap() {  
		Map<String,String[]> paraMap = super.getParameterMap();  
        // 对于paraMap为空的直接return  
        if (null == paraMap || paraMap.isEmpty()) {  
            return paraMap;  
        }  
          
        //super.getParameterMap()不允许任何修改,所以只能做深拷贝  
        Map<String, String[]> paraMapCopy = new HashMap<String, String[]>();  
        //实际上putAll只对基本类型深拷贝有效,如果是自定义类型,则要找其他办法  
        paraMapCopy.putAll(paraMap);  
          
        for (Map.Entry<String, String[]> entry : paraMapCopy.entrySet()) {  
            String[] values     = entry.getValue();  
            if (null == values) {  
                continue;  
            }  
            String[] newValues  = new String[values.length];  
            for (int i = 0; i < values.length; i++) {  
                newValues[i] = getBasicHtmlandimage(values[i]);  
            }  
            entry.setValue(newValues);  
        }  
        return paraMapCopy;  
    }  
      
    private static String getBasicHtmlandimage(String html) {  
	    if (html == null)  
	        return null;  
	    return Jsoup.clean(html, Whitelist.basicWithImages());  
	}  
}  

2、新建XssHandler拦截器:

/**  
 * xss拦截器  
 * @author QinHaiLin  
 *  
 */  
public class XssHandler extends Handler {  
  
  
	// 排除的url,使用的target.startsWith匹配的  
   private String excludePattern;  
      
   /**  
    * 忽略列表,使用正则排除url  
    * @param exclude  
    */  
   public XssHandler(String excludePattern) {  
       this.excludePattern = excludePattern;  
   }  
  
	@Override  
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {  
  
		java.util.regex.Pattern pattern = Pattern.compile(excludePattern);  
		//带.表示非action请求,忽略(其实不太严谨,如果是伪静态,比如.html会被错误地排除);匹配excludePattern的,忽略  
       if (target.indexOf(".") == -1 && !(!StringUtil.isBlank(excludePattern) && pattern.matcher(target).find() ) ){  
           request = new XssHttpServletRequestWrapper(request);  
       }  
         
       next.handle(target, request, response, isHandled);  
         
	}  
  
}  

3、在MainConfig里面配置XssHandler拦截器,那么对XSS的存储型攻击就可以进行有效的防御了。

 /**  
	 * 配置全局处理器  
	 */  
	@Override  
	public void configHandler(Handlers me) {  
		/** 配置druid监控 **/  
		me.add(DruidKit.getDruidStatViewHandler());   
		// 路由处理  
		me.add(new CommonHandler());  
		// XSS过滤  
		me.add(new XssHandler("^\\/portal/form/view.*"));  
	}


二、CSRF跨站请求伪造防御


针对CSRF跨站请求伪造,JFinal-layui主要是对添加、修改的业务表单加入token验证机制,这样就可以解决重要业务操作的安全性。我们的拦截是全局验证拦截,在开发功能过程中就是顺手做的事情,简单高效。

1、利用JFinal的token机制,创建自己的TokenService:

/**  
 * token  
 * @author QinHaiLin  
 * @date 2020-02-14  
 */  
public class TokenService {  
  
	/**  
	 * 创建token  
	 * @param c  
	 */  
	public void createToken(Controller c){  
		TokenManager.createToken(c, Const.DEFAULT_TOKEN_NAME, Const.DEFAULT_SECONDS_OF_TOKEN_TIME_OUT);  
	}  
	  
	/**  
	 * 验证token  
	 * @param c  
	 */  
	public boolean validateToken(Controller c){  
		return TokenManager.validateToken(c, Const.DEFAULT_TOKEN_NAME);  
	}  
}  

2、再创建TokenInterceptor的拦截器进行全局拦截验证:

/**  
 * token拦截器  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class TokenInterceptor implements Interceptor {  
  
	@Inject  
	TokenService tokenService;  
	  
	@Override  
	public void intercept(Invocation inv) {  
		Controller c=inv.getController();  
		String methName=inv.getMethod().getName();  
		  
		//给默认的添加、修改方法添加token  
		if(methName.equals("add")||methName.equals("edit")){  
			tokenService.createToken(c);		  
		}  
		  
		//验证token  
		if(methName.equals("save")||methName.equals("update")){  
			boolean b=tokenService.validateToken(c);  
			if(!b){  
				boolean isAjax="XMLHttpRequest".equalsIgnoreCase(c.getHeader("X-Requested-With"));  
				if(isAjax){  
					c.renderJson(Ret.fail("msg", "token验证不通过,请刷新页面"));  
				}else{  
					c.setAttr("msg", "token验证不通过");  
					c.renderError(403);  
				}  
				return;  
			}  
			//添加修改成功后,返回对的页面,此处是解决业务验证不通过的情况,如:添加用户时,如果存在用户编号,那么需要重新填写,此时就要重新赋值新的token  
			tokenService.createToken(c);  
		}  
		inv.invoke();  
	}  
  
}  

3、在MainConfig配置成全局拦截器即可:

/**  
	 * 配置全局拦截器  
	 */  
	@Override  
	public void configInterceptor(Interceptors me) {  
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());  
		me.addGlobalActionInterceptor(new SessionInterceptor());  
		me.addGlobalActionInterceptor(new ExceptionInterceptor());  
		//表单token验证拦截器  
		me.addGlobalActionInterceptor(new TokenInterceptor());  
		me.addGlobalActionInterceptor(new LoggerInterceptor());  
	}  

4、在添加修改的操作表单输出token:#(token)

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器


三、代码生成器


为满足广大用户要求,还是决定把代码生成器集成进来,那么有了这一神器,就可以把那些繁琐重复的开发工作交给代码器了,一键多表生成代码文件,页面操作简单,直接生成代码文件到项目当中,刷新重启项目即可。


1、代码生成器操作页面,选择需要的表,可多选,点击选择按钮即可:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

2、点击生成代码,这是预览代码,还没有真正创建代码文件,点击下载代码才是最终在项目中创建:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

3、点击下载代码,创建文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

4、刷新项目,就能在预先设置的package里面创建对应的Java文件了,html目录也是按照相应规则创建对应的目录:

java文件: html文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

5、此时代码文件已经创建好了,还需要最关键的一步,那就是把_MappingKit.java里面在数据库表映射关系配置到主配置文件中:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

6、最后就是启动项目,配置菜单权限即可访问了。

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器
感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18436.html



前言

JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会前端layui,也能轻松掌握使用。


JFinal-layui v1.4.2 新增XSS、CSRF防御和代码生成器,加强web安全和提升开发效率!在工作中发现,一些公司在给客户开发系统的时候,都很容易忽略了web安全的内容,或者根本不考虑web安全漏洞,所以这样开发出来的系统本身就是存在很大的安全隐患,只要稍微有点技术的人员就能进行XSS攻击和CSRF跨站请求伪造!因为本人有过一段难忘的web安全漏洞修复的经历,所以把积累的一些经验应用到JFinal-layui中,让系统更加安全可靠!

v1.4.2更新内容详情:


一、XSS攻击防御


JFinal-layui主要是对XSS的存储型攻击进行防御,把用户输入的数据都进行XSS过滤,避免对系统造成不良影响。利用JFInal的Handler来实现,重写HttpServletRequestWrapper非常简单。


1、自定义XssHttpServletRequestWrapper类,重写getParameter:

/**  
 * xss过滤处理  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{  
	  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
   
    /**  
     * 重写并过滤getParameter方法  
     */  
    @Override  
    public String getParameter(String name) {  
        return getBasicHtmlandimage(super.getParameter(name));  
          
    }  
       
    /**  
     * 重写并过滤getParameterValues方法  
     */  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if (null == values){  
            return null;  
        }  
        for (int i = 0; i < values.length; i++) {  
            values[i] = getBasicHtmlandimage(values[i]);  
        }  
        return values;  
    }  
       
    /**  
     * 重写并过滤getParameterMap方法  
     */  
    @Override  
    public Map<String,String[]> getParameterMap() {  
		Map<String,String[]> paraMap = super.getParameterMap();  
        // 对于paraMap为空的直接return  
        if (null == paraMap || paraMap.isEmpty()) {  
            return paraMap;  
        }  
          
        //super.getParameterMap()不允许任何修改,所以只能做深拷贝  
        Map<String, String[]> paraMapCopy = new HashMap<String, String[]>();  
        //实际上putAll只对基本类型深拷贝有效,如果是自定义类型,则要找其他办法  
        paraMapCopy.putAll(paraMap);  
          
        for (Map.Entry<String, String[]> entry : paraMapCopy.entrySet()) {  
            String[] values     = entry.getValue();  
            if (null == values) {  
                continue;  
            }  
            String[] newValues  = new String[values.length];  
            for (int i = 0; i < values.length; i++) {  
                newValues[i] = getBasicHtmlandimage(values[i]);  
            }  
            entry.setValue(newValues);  
        }  
        return paraMapCopy;  
    }  
      
    private static String getBasicHtmlandimage(String html) {  
	    if (html == null)  
	        return null;  
	    return Jsoup.clean(html, Whitelist.basicWithImages());  
	}  
}  

2、新建XssHandler拦截器:

/**  
 * xss拦截器  
 * @author QinHaiLin  
 *  
 */  
public class XssHandler extends Handler {  
  
  
	// 排除的url,使用的target.startsWith匹配的  
   private String excludePattern;  
      
   /**  
    * 忽略列表,使用正则排除url  
    * @param exclude  
    */  
   public XssHandler(String excludePattern) {  
       this.excludePattern = excludePattern;  
   }  
  
	@Override  
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {  
  
		java.util.regex.Pattern pattern = Pattern.compile(excludePattern);  
		//带.表示非action请求,忽略(其实不太严谨,如果是伪静态,比如.html会被错误地排除);匹配excludePattern的,忽略  
       if (target.indexOf(".") == -1 && !(!StringUtil.isBlank(excludePattern) && pattern.matcher(target).find() ) ){  
           request = new XssHttpServletRequestWrapper(request);  
       }  
         
       next.handle(target, request, response, isHandled);  
         
	}  
  
}  

3、在MainConfig里面配置XssHandler拦截器,那么对XSS的存储型攻击就可以进行有效的防御了。

 /**  
	 * 配置全局处理器  
	 */  
	@Override  
	public void configHandler(Handlers me) {  
		/** 配置druid监控 **/  
		me.add(DruidKit.getDruidStatViewHandler());   
		// 路由处理  
		me.add(new CommonHandler());  
		// XSS过滤  
		me.add(new XssHandler("^\\/portal/form/view.*"));  
	}


二、CSRF跨站请求伪造防御


针对CSRF跨站请求伪造,JFinal-layui主要是对添加、修改的业务表单加入token验证机制,这样就可以解决重要业务操作的安全性。我们的拦截是全局验证拦截,在开发功能过程中就是顺手做的事情,简单高效。

1、利用JFinal的token机制,创建自己的TokenService:

/**  
 * token  
 * @author QinHaiLin  
 * @date 2020-02-14  
 */  
public class TokenService {  
  
	/**  
	 * 创建token  
	 * @param c  
	 */  
	public void createToken(Controller c){  
		TokenManager.createToken(c, Const.DEFAULT_TOKEN_NAME, Const.DEFAULT_SECONDS_OF_TOKEN_TIME_OUT);  
	}  
	  
	/**  
	 * 验证token  
	 * @param c  
	 */  
	public boolean validateToken(Controller c){  
		return TokenManager.validateToken(c, Const.DEFAULT_TOKEN_NAME);  
	}  
}  

2、再创建TokenInterceptor的拦截器进行全局拦截验证:

/**  
 * token拦截器  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class TokenInterceptor implements Interceptor {  
  
	@Inject  
	TokenService tokenService;  
	  
	@Override  
	public void intercept(Invocation inv) {  
		Controller c=inv.getController();  
		String methName=inv.getMethod().getName();  
		  
		//给默认的添加、修改方法添加token  
		if(methName.equals("add")||methName.equals("edit")){  
			tokenService.createToken(c);		  
		}  
		  
		//验证token  
		if(methName.equals("save")||methName.equals("update")){  
			boolean b=tokenService.validateToken(c);  
			if(!b){  
				boolean isAjax="XMLHttpRequest".equalsIgnoreCase(c.getHeader("X-Requested-With"));  
				if(isAjax){  
					c.renderJson(Ret.fail("msg", "token验证不通过,请刷新页面"));  
				}else{  
					c.setAttr("msg", "token验证不通过");  
					c.renderError(403);  
				}  
				return;  
			}  
			//添加修改成功后,返回对的页面,此处是解决业务验证不通过的情况,如:添加用户时,如果存在用户编号,那么需要重新填写,此时就要重新赋值新的token  
			tokenService.createToken(c);  
		}  
		inv.invoke();  
	}  
  
}  

3、在MainConfig配置成全局拦截器即可:

/**  
	 * 配置全局拦截器  
	 */  
	@Override  
	public void configInterceptor(Interceptors me) {  
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());  
		me.addGlobalActionInterceptor(new SessionInterceptor());  
		me.addGlobalActionInterceptor(new ExceptionInterceptor());  
		//表单token验证拦截器  
		me.addGlobalActionInterceptor(new TokenInterceptor());  
		me.addGlobalActionInterceptor(new LoggerInterceptor());  
	}  

4、在添加修改的操作表单输出token:#(token)

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器


三、代码生成器


为满足广大用户要求,还是决定把代码生成器集成进来,那么有了这一神器,就可以把那些繁琐重复的开发工作交给代码器了,一键多表生成代码文件,页面操作简单,直接生成代码文件到项目当中,刷新重启项目即可。


1、代码生成器操作页面,选择需要的表,可多选,点击选择按钮即可:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

2、点击生成代码,这是预览代码,还没有真正创建代码文件,点击下载代码才是最终在项目中创建:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

3、点击下载代码,创建文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

4、刷新项目,就能在预先设置的package里面创建对应的Java文件了,html目录也是按照相应规则创建对应的目录:

java文件: html文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

5、此时代码文件已经创建好了,还需要最关键的一步,那就是把_MappingKit.java里面在数据库表映射关系配置到主配置文件中:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

6、最后就是启动项目,配置菜单权限即可访问了。

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器
感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18436.html



前言

JFinal-layui 极速开发企业应用管理系统,是以 JFinal+layui 为核心的企业应用项目架构,利用 JFinal 的特性与 layui 完美结合,达到快速启动项目的目的。让开发更简单高效,即使你不会前端layui,也能轻松掌握使用。


JFinal-layui v1.4.2 新增XSS、CSRF防御和代码生成器,加强web安全和提升开发效率!在工作中发现,一些公司在给客户开发系统的时候,都很容易忽略了web安全的内容,或者根本不考虑web安全漏洞,所以这样开发出来的系统本身就是存在很大的安全隐患,只要稍微有点技术的人员就能进行XSS攻击和CSRF跨站请求伪造!因为本人有过一段难忘的web安全漏洞修复的经历,所以把积累的一些经验应用到JFinal-layui中,让系统更加安全可靠!

v1.4.2更新内容详情:


一、XSS攻击防御


JFinal-layui主要是对XSS的存储型攻击进行防御,把用户输入的数据都进行XSS过滤,避免对系统造成不良影响。利用JFInal的Handler来实现,重写HttpServletRequestWrapper非常简单。


1、自定义XssHttpServletRequestWrapper类,重写getParameter:

/**  
 * xss过滤处理  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper{  
	  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
   
    /**  
     * 重写并过滤getParameter方法  
     */  
    @Override  
    public String getParameter(String name) {  
        return getBasicHtmlandimage(super.getParameter(name));  
          
    }  
       
    /**  
     * 重写并过滤getParameterValues方法  
     */  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if (null == values){  
            return null;  
        }  
        for (int i = 0; i < values.length; i++) {  
            values[i] = getBasicHtmlandimage(values[i]);  
        }  
        return values;  
    }  
       
    /**  
     * 重写并过滤getParameterMap方法  
     */  
    @Override  
    public Map<String,String[]> getParameterMap() {  
		Map<String,String[]> paraMap = super.getParameterMap();  
        // 对于paraMap为空的直接return  
        if (null == paraMap || paraMap.isEmpty()) {  
            return paraMap;  
        }  
          
        //super.getParameterMap()不允许任何修改,所以只能做深拷贝  
        Map<String, String[]> paraMapCopy = new HashMap<String, String[]>();  
        //实际上putAll只对基本类型深拷贝有效,如果是自定义类型,则要找其他办法  
        paraMapCopy.putAll(paraMap);  
          
        for (Map.Entry<String, String[]> entry : paraMapCopy.entrySet()) {  
            String[] values     = entry.getValue();  
            if (null == values) {  
                continue;  
            }  
            String[] newValues  = new String[values.length];  
            for (int i = 0; i < values.length; i++) {  
                newValues[i] = getBasicHtmlandimage(values[i]);  
            }  
            entry.setValue(newValues);  
        }  
        return paraMapCopy;  
    }  
      
    private static String getBasicHtmlandimage(String html) {  
	    if (html == null)  
	        return null;  
	    return Jsoup.clean(html, Whitelist.basicWithImages());  
	}  
}  

2、新建XssHandler拦截器:

/**  
 * xss拦截器  
 * @author QinHaiLin  
 *  
 */  
public class XssHandler extends Handler {  
  
  
	// 排除的url,使用的target.startsWith匹配的  
   private String excludePattern;  
      
   /**  
    * 忽略列表,使用正则排除url  
    * @param exclude  
    */  
   public XssHandler(String excludePattern) {  
       this.excludePattern = excludePattern;  
   }  
  
	@Override  
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {  
  
		java.util.regex.Pattern pattern = Pattern.compile(excludePattern);  
		//带.表示非action请求,忽略(其实不太严谨,如果是伪静态,比如.html会被错误地排除);匹配excludePattern的,忽略  
       if (target.indexOf(".") == -1 && !(!StringUtil.isBlank(excludePattern) && pattern.matcher(target).find() ) ){  
           request = new XssHttpServletRequestWrapper(request);  
       }  
         
       next.handle(target, request, response, isHandled);  
         
	}  
  
}  

3、在MainConfig里面配置XssHandler拦截器,那么对XSS的存储型攻击就可以进行有效的防御了。

 /**  
	 * 配置全局处理器  
	 */  
	@Override  
	public void configHandler(Handlers me) {  
		/** 配置druid监控 **/  
		me.add(DruidKit.getDruidStatViewHandler());   
		// 路由处理  
		me.add(new CommonHandler());  
		// XSS过滤  
		me.add(new XssHandler("^\\/portal/form/view.*"));  
	}


二、CSRF跨站请求伪造防御


针对CSRF跨站请求伪造,JFinal-layui主要是对添加、修改的业务表单加入token验证机制,这样就可以解决重要业务操作的安全性。我们的拦截是全局验证拦截,在开发功能过程中就是顺手做的事情,简单高效。

1、利用JFinal的token机制,创建自己的TokenService:

/**  
 * token  
 * @author QinHaiLin  
 * @date 2020-02-14  
 */  
public class TokenService {  
  
	/**  
	 * 创建token  
	 * @param c  
	 */  
	public void createToken(Controller c){  
		TokenManager.createToken(c, Const.DEFAULT_TOKEN_NAME, Const.DEFAULT_SECONDS_OF_TOKEN_TIME_OUT);  
	}  
	  
	/**  
	 * 验证token  
	 * @param c  
	 */  
	public boolean validateToken(Controller c){  
		return TokenManager.validateToken(c, Const.DEFAULT_TOKEN_NAME);  
	}  
}  

2、再创建TokenInterceptor的拦截器进行全局拦截验证:

/**  
 * token拦截器  
 * @author QinHaiLin  
 * @date 2020-02-13  
 */  
public class TokenInterceptor implements Interceptor {  
  
	@Inject  
	TokenService tokenService;  
	  
	@Override  
	public void intercept(Invocation inv) {  
		Controller c=inv.getController();  
		String methName=inv.getMethod().getName();  
		  
		//给默认的添加、修改方法添加token  
		if(methName.equals("add")||methName.equals("edit")){  
			tokenService.createToken(c);		  
		}  
		  
		//验证token  
		if(methName.equals("save")||methName.equals("update")){  
			boolean b=tokenService.validateToken(c);  
			if(!b){  
				boolean isAjax="XMLHttpRequest".equalsIgnoreCase(c.getHeader("X-Requested-With"));  
				if(isAjax){  
					c.renderJson(Ret.fail("msg", "token验证不通过,请刷新页面"));  
				}else{  
					c.setAttr("msg", "token验证不通过");  
					c.renderError(403);  
				}  
				return;  
			}  
			//添加修改成功后,返回对的页面,此处是解决业务验证不通过的情况,如:添加用户时,如果存在用户编号,那么需要重新填写,此时就要重新赋值新的token  
			tokenService.createToken(c);  
		}  
		inv.invoke();  
	}  
  
}  

3、在MainConfig配置成全局拦截器即可:

/**  
	 * 配置全局拦截器  
	 */  
	@Override  
	public void configInterceptor(Interceptors me) {  
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());  
		me.addGlobalActionInterceptor(new SessionInterceptor());  
		me.addGlobalActionInterceptor(new ExceptionInterceptor());  
		//表单token验证拦截器  
		me.addGlobalActionInterceptor(new TokenInterceptor());  
		me.addGlobalActionInterceptor(new LoggerInterceptor());  
	}  

4、在添加修改的操作表单输出token:#(token)

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器


三、代码生成器


为满足广大用户要求,还是决定把代码生成器集成进来,那么有了这一神器,就可以把那些繁琐重复的开发工作交给代码器了,一键多表生成代码文件,页面操作简单,直接生成代码文件到项目当中,刷新重启项目即可。


1、代码生成器操作页面,选择需要的表,可多选,点击选择按钮即可:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

2、点击生成代码,这是预览代码,还没有真正创建代码文件,点击下载代码才是最终在项目中创建:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

3、点击下载代码,创建文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

4、刷新项目,就能在预先设置的package里面创建对应的Java文件了,html目录也是按照相应规则创建对应的目录:

java文件: html文件:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

5、此时代码文件已经创建好了,还需要最关键的一步,那就是把_MappingKit.java里面在数据库表映射关系配置到主配置文件中:

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

6、最后就是启动项目,配置菜单权限即可访问了。

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器

【开源资讯】JFinal-layui v1.4.2 来袭,XSS、CSRF防御、代码器