ITPub博客

首页 > 数据库 > 数据库开发技术 > 互联网金融产品实战——安全开发篇

互联网金融产品实战——安全开发篇

原创 数据库开发技术 作者:MavenTalk 时间:2016-09-08 08:59:18 0 删除 编辑


        说到安全开发,总绕不开两个词:OWASP(Open Web Application Security Project)和CWE(Common Weakness Enumeration),针对其中的某些关键点再结合自身业务的特点,逐个作出应对。



        (看不清时,点击查看大图)

    

        下文针对某些点,并结合之前的项目经历,简单列出几个解决方法供大家参考。


一、CSRF跨站请求伪造过滤器,杜绝不信任的站点非法请求服务。一些图片防盗链的网站采用类似Refer机制完成的。

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse resp = (HttpServletResponse) response;

        String sourceRefer = req.getHeader("Referer");

        //允许配置多个可信赖Referer,存储在资源文件中

        String allowRefers = bundle.getString("CSRF.NORMAL.REFERER");

        List<String> urlList = new ArrayList<String>();

        if (StringUtil.isNotEmpty(allowRefers)) {

            String[] refers = allowRefers.split("#");

            if (ArrayUtils.isNotEmpty(refers)) {

                for (int i = 0; i < refers.length; i++) {

                    String string = refers[i];

                    urlList.add(string);

                }

            }

        }


        if (StringUtil.isNotBlank(sourceRefer)) {

            //将http or https等协议头 过滤掉,形如http://www.baidu.com

            String[] srcRef = sourceRefer.trim().split("//");

            if (ArrayUtils.isNotEmpty(srcRef)) {

                //非正式环境下,有端口配置,再重新分隔,形如http://test.backkom.com:8080/ofs

                String[] srcRefer = srcRef[1].split(":");

                if (srcRefer.length == 1) {

                    //正式环境下,均是域名,形如http://www.web2.0bk.com/news/12123.html

                    String[] srcReferSplit = srcRefer[0].split("/");

                    if (!urlList.contains(srcReferSplit[0])) {

                        logger.info("UnReliable referer :" + srcReferSplit[0]);

                        //不信任时不作任何展示,直接跳转至500页面,前端js拿到此响应码,跳转到500页面

                        resp.setStatus(500);

                        String redirectUrl = bundle.getString("CSRF.REDIRECT.URL");

                        resp.setHeader("Location", redirectUrl);

                    } else {

                        chain.doFilter(req, resp);

                    }

                } else {

                    if (!urlList.contains(srcRefer[0])) {

                        logger.info("UnReliable referer :" + srcRefer[0]);

                        //不信任时不作任何展示,直接跳转至500页面,前端js拿到此响应码,跳转到500页面

                        resp.setStatus(500);

                        String redirectUrl = bundle.getString("CSRF.REDIRECT.URL");

                        resp.setHeader("Location", redirectUrl);

                    } else {

                        chain.doFilter(req, resp);

                    }

                }

            } else {

                chain.doFilter(req, resp);

            }


        } else {

            chain.doFilter(req, resp);

        }

    }


二、Session超时过滤器,过滤请求,判断请求是否失效,失效后直接退出要求再次登陆

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

        String countStr = bundle.getString("filter.url.count");

        int urlCnts = Integer.valueOf(countStr);

        String tempStr = "filter.url";

        StringBuffer urlPre = new StringBuffer();

        for (int i = 0; i < urlCnts; i++) {

            String filterUrl = bundle.getString(urlPre.append(tempStr).append(i).toString());

            if (StringUtils.isNotEmpty(filterUrl)) {

                urlList.add(filterUrl);

            }

            urlPre.setLength(0);

        }

        // 初始化需要拦截的文件夹

        String include = filterConfig.getInitParameter("include");

        if (include != null) {

            StringTokenizer st = new StringTokenizer(include, ",");

            list.clear();

            while (st.hasMoreTokens()) {

                list.add(st.nextToken());

            }

        }

    }


    @Override

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse resp = (HttpServletResponse) response;


        //不含参数的路径

        String servletPath = req.getServletPath();

        StringBuilder jsStr = new StringBuilder("");

        StringBuilder sb = new StringBuilder();


        Date d = new Date();

        String ts = String.valueOf(d.getTime());

        sb.append(bundle.getString("tomcat.admin.login.url")).append(EztpfpConstants.LOGIN_ADMIN_URL).append(bundle.getString("tomcat.admin.url")).append("?ts=").append(ts);

        //当用户没有登录时,需要跳转到的登陆链接

        String adminLoginReturnUrl = sb.toString();

        String adminJumpUrl = null;

        if (StringUtils.isNotEmpty(adminLoginReturnUrl)) {

            adminJumpUrl = jsStr.append(adminLoginReturnUrl).toString();

        }

        //获取用户信息,判断用户是否登录

        UserInfoBean userInfoBean = (UserInfoBean) getSession().getAttribute("online.user")

        //是否是ajax请求

        String xRequested = req.getHeader("X-Requested-With");

        if (userInfoBean == null) {

            //至过滤*.action,*.html的链接

            if ((servletPath.contains(".action") || servletPath.contains(".html")) && !urlList.contains(servletPath)) {

                logger.info(FunIMsgFormat.MsgStyle.DEFAULT_LOG

                        .getFormat(EztpfpConstants.LOGGER_TXT_MONITOR),

                        new Object[] { "", "doFilter", "进入session过滤器拦截路径!", new Date() });

                //如果是ajax请求,返回给前台

                if ("XMLHttpRequest".equals(xRequested)) {

                    setJsonResponse(resp, adminLoginReturnUrl);

                } else {

                    //不是ajax请求,直接跳转登陆页面,由JS处理跳转功能

                    req.setAttribute("msg", "您还没有登录或登录已超时,请重新登录!");

                    resp.sendRedirect(adminJumpUrl);

                }

            } else {

                chain.doFilter(req, resp);

            }

        } else {

            chain.doFilter(req, resp);

        }

    }

    private void setJsonResponse(HttpServletResponse res, String redirectUrl) throws IOException {

        res.setStatus(800);

        res.setHeader("Location", redirectUrl);

    }

}

三、关键交易防重技术


  (看不清时,点击查看大图)

四、XSS过滤器

        可以利用OWASP的一个开源项目:AntiSamy,来解决XSS攻击问题。AntiSamy是可以确保前端输入的HTML、CSS、JavaScript符合规范的API。确保用户无法在HTML中提交恶意代码,而这些恶意代码通常被输入到个人资料、评论等会被服务端存储的数据中,以造成服务的不友好或者破坏正常服务。项目地址:https://code.google.com/archive/p/owaspantisamy/downloads,扩展阅读可网络中查找相关资料。

        另MyBatis中已经实现了对SQL的预编译,但针对${xxx}参数的情况需要着重关注,因为存在SQL注入的可能性。


五、校验再校验

        特别针对后台权限开发时,以往的做法是这样的:根据登陆用户的不同,找到其对应的菜单展现出来,这样权限就控制住了。这种做法存在一种隐患,如果此用户通过其它渠道得到某个功能的访问链接地址,直接在URL中输入此链接来操作对应的功能,那么权限控制就无从谈起。

        针对此种情况,可适当增加权限再校验的步骤,根据提交过来的请求,再次校验权限是否足够,可通过拦截器实现。


        其它安全注意项,还很多,这里不一一展开了,可在项目中实际摸索,找出合适的解决方案。


乾坤大挪移--->:

余额理财产品—开发实战

互联网金融产品实战——备战篇

互联网金融产品实战——设计篇

互联网金融产品实战——开发篇

歪脖贰点零 ∣一个有逼格的WEB2.0
长按,识别二维码,加关注


原文作者:MavenTalk;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2016-07-13

  • 博文量
    461
  • 访问量
    189224