美文网首页
csrf 防御

csrf 防御

作者: 范一婷 | 来源:发表于2016-11-21 20:48 被阅读136次

    http 中 origin 的含义:
    跨域资源共享策略(cors)中,当浏览器发出跨域请求,会自动为请求头带上 origin 头部

    防护 csrf 的方法:
    1.通过请求头判断请求是否与当前页面同源
    检验 referer 字段,如果不存在则拒绝该请求!
    注意,在检验的时候容易被绕过。如果你的站点是 site.com,要确保referer中是 site.com.attacker.com 不会被允许!

     // 从 HTTP 头中取得 Referer 值
     String referer=request.getHeader("Referer"); 
     // 判断 Referer 是否以 bank.example 开头
     if((referer!=null) &&(referer.trim().startsWith(“bank.example”))){ 
        chain.doFilter(request, response); 
     }else{ 
        request.getRequestDispatcher(“error.jsp”).forward(request,response); 
     }
    

    2.csrf token
    当用户请求一个网页时候,web 应用生成一个与当前 session 相关的 token,这个值存在服务器的 session 中,并且把 token 发送给客户端。当客户端发送"修改密码"的请求的时候,在表单中用一个隐藏字段发送该 token ,服务器验证验证 session 中存储的 token 与客户端发送来的 token 是否相同,如果不相同或者没有 token ,则抛弃该请求。

    在 filter 中验证请求中的 token

     HttpServletRequest req = (HttpServletRequest)request; 
     HttpSession s = req.getSession(); 
    
     // 从 session 中得到 csrftoken 属性
     String sToken = (String)s.getAttribute(“csrftoken”); 
     if(sToken == null){ 
    
        // 产生新的 token 放入 session 中
        sToken = generateToken(); 
        s.setAttribute(“csrftoken”,sToken); 
        chain.doFilter(request, response); 
     } else{ 
    
        // 从 HTTP 头中取得 csrftoken 
        String xhrToken = req.getHeader(“csrftoken”); 
    
        // 从请求参数中取得 csrftoken 
        String pToken = req.getParameter(“csrftoken”); 
        if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){ 
            chain.doFilter(request, response); 
        }else if(sToken != null && pToken != null && sToken.equals(pToken)){ 
            chain.doFilter(request, response); 
        }else{ 
            request.getRequestDispatcher(“error.jsp”).forward(request,response); 
        } 
     }
    
    

    在客户端对于请求加入 token

    function appendToken(){ 
        updateForms(); 
        updateTags(); 
     } 
    
     function updateForms() { 
        // 得到页面中所有的 form 元素
        var forms = document.getElementsByTagName('form'); 
        for(i=0; i<forms.length; i++) { 
            var url = forms[i].action; 
    
            // 如果这个 form 的 action 值为空,则不附加 csrftoken 
            if(url == null || url == "" ) continue; 
    
            // 动态生成 input 元素,加入到 form 之后
            var e = document.createElement("input"); 
            e.name = "csrftoken"; 
            e.value = token; 
            e.type="hidden"; 
            forms[i].appendChild(e); 
        } 
     } 
    
     function updateTags() { 
        var all = document.getElementsByTagName('a'); 
        var len = all.length; 
    
        // 遍历所有 a 元素
        for(var i=0; i<len; i++) { 
            var e = all[i]; 
            updateTag(e, 'href', token); 
        } 
     } 
    
     function updateTag(element, attr, token) { 
        var location = element.getAttribute(attr); 
        if(location != null && location != '' '' ) { 
            var fragmentIndex = location.indexOf('#'); 
            var fragment = null; 
            if(fragmentIndex != -1){ 
    
                //url 中含有只相当页的锚标记
                fragment = location.substring(fragmentIndex); 
                location = location.substring(0,fragmentIndex); 
            } 
            
            var index = location.indexOf('?'); 
    
            if(index != -1) { 
                //url 中已含有其他参数
                location = location + '&csrftoken=' + token; 
            } else { 
                //url 中没有其他参数
                location = location + '?csrftoken=' + token; 
            } 
            if(fragment != null){ 
                location += fragment; 
            } 
            
            element.setAttribute(attr, location); 
        } 
     }
    

    相关文章

      网友评论

          本文标题:csrf 防御

          本文链接:https://www.haomeiwen.com/subject/ucoupttx.html