angularjs - AngularJS的Gorilla CSRF

标签 angularjs go gorilla

我正在尝试使AngularJS与Gorilla CSRF一起用于我的Web应用程序,但是我找不到很多文档,因此我不确定从哪里开始。我应该为每个X-CSRF-Token请求设置一个GET还是当用户访问主页时像现在一样执行该操作?另外,如何使AngularJS CSRF保护与Gorilla CSRF一起使用?我需要做一些比较吗?任何示例代码将不胜感激。

这是我的代码:

package main

import (
    "github.com/gorilla/csrf"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()


    r.HandleFunc("/", Home).Methods("GET")
    // Other routes handling goes here

    http.ListenAndServe(":8000",
        csrf.Protect([]byte("32-byte-long-auth-key"))(r))
}

func Home(w http.ResponseWriter, r *http.Request) {

    w.Header().Set("X-CSRF-Token", csrf.Token(r))
}
// More routes

最佳答案

您可能提出的问题可能有点广泛,但总的来说您在滥用这些工具,因此我将尝试解释一些基本概念。您使用的应用程序使用“双重提交”模式进行CSRF保护。这需要更改客户端和服务器代码库。服务器不应设置X-CSRF-Token header ,即客户端的 Angular 色。实际上,最近我实际上已经从零开始实现了一些反CSRF解决方案,它们非常简单(都是双重提交模式)。我还使用了MSTF和Apache之类的 vendor 提供的一些程序包(必须在20多年的各种堆栈上的应用程序中实现CSRF)。

在双提交模式中,服务器应设置一个具有随机值的cookie(如guid),该cookie必须标记为安全。您也可以将其设置为httponly,但是这将需要您在前端资源上做很多工作。在客户端,处理此问题的最简单方法是实现一些JavaScript,该JavaScript读取cookie值并将其添加为任何POST请求之前的 header 。您通常不需要保护GET。您可以,但是如果您的GET在服务器端执行了构造性/破坏性的事情,那么您就滥用了HTTP动词,我将通过使那些请求变为POST而不是尝试保护每个单个请求来纠正这一点。

在服务器端,最好在所有请求都进入的公共(public)位置预先进行CSRF检查。当POST进入时,服务器应读取cookie值,检查 header 值并进行比较。如果它们相等,则应允许请求通过,如果不相等,则应使用403之类的命令引导它们。这样做之后,服务器应重写cookie值(最好只使用一次)。

您的客户端脚本可以包含类似下面的代码,只需确保资源在每次页面加载时都使用,并且您不使用表单提交即可,这将覆盖所有内容。如果提交表单,则需要其他类似的代码来处理。一些方法更喜欢在DOM服务器端写入值。例如,在.NET中,CSRF库将值设置为HTTPOnly和Secure,并期望开发人员在项目中的每个单个cshtml文件中以每种形式放置占位符 token ...我个人认为这非常愚蠢且效率低下。无论您如何执行此操作,您都可能需要做一些自定义工作。 Angular不会为 gorilla CSRF库实现前端。 gorilla可能不会为您的客户端提供JavaScript,因为它是一个API库。无论如何,基本的JavaScript示例;

// three functions to enable CSRF protection in the client. Sets the nonce header with value from cookie
// prior to firing any HTTP POST.
function addXMLRequestCallback(callback) {
    var oldSend;
    if (!XMLHttpRequest.sendcallback) {
        XMLHttpRequest.sendcallback = callback;
        oldSend = XMLHttpRequest.prototype.send;

        // override the native send()
        XMLHttpRequest.prototype.send = function () {
            XMLHttpRequest.sendcallback(this);

            if (!Function.prototype.apply) {
                Function.prototype.apply = function (self, oArguments) {
                    if (!oArguments) {
                        oArguments = [];
                    }
                    self.__func = this;
                    self.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
                    delete self.__func;
                };
            }

            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}

addXMLRequestCallback(function (xhr) {
    xhr.setRequestHeader('X-CSRF-Token', getCookie('X-CSRF-Cookie'));
});

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}

现在,如果您可以缩小问题的范围,我可以提供一些更具体的指导,但这只是一个猜测(也许我会在有空的时候阅读他们的文档)。如果您使用csrf.Protect,Gorilla会自动设置您的cookie并在服务器端为您检查。您已在Go中设置 header 的代码,即上述JavaScript所需的代码。如果您在服务器端设置 header ,则根本不提供安全性。这需要在浏览器中进行。如果您将值与所有请求一起发送, gorilla 很可能会为您支付其余的费用。

关于问题空间的其他一些随机想法。根据经验,如果攻击者无法重播请求,则他们可能无法CSRF您。这就是为什么这种简单方法如此有效的原因。每个传入请求都具有一个需要传递的随机GUID值。您可以将该值存储在cookie中,因此不必担心跨服务器的 session 移动(如果您不使用双提交模式,则需要共享数据存储服务器端;此cookie header 值比较业务) )。在当前硬件限制下,此值没有真正的可能性。浏览器中的单一来源策略可防止攻击者读取您设置的cookie值(如果将域设置为安全,则只有域中的脚本才能访问它)。唯一的利用方法是,如果用户以前曾被XSS利用过,我的意思是,这样做会破坏执行CSRF的目的,因为攻击者已经具有更多的控制/能力来利用XSS进行恶意操作。

关于angularjs - AngularJS的Gorilla CSRF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33678311/

相关文章:

javascript - Breeze JS为什么要为每个工作单元创建一个新的entityManagerProvider?

go - 转义 json 对象以创建 kafka 轴突有效载荷

Go Gorilla RecoveryHandler 编译报错

go - Gorilla mux 路由器不提供静态内容——比如 style.css、script.js

Golang http mux 更改处理函数

angularjs - 如何在 Angular Material 设计的网格列表中隐藏网格图 block ?

javascript - Angular 多选

javascript - 将文本添加到 Angular SVG 圆形进度条

go - 如何进行简单的 SSH x11 转发

reflection - 是否可以使用反射来做类似于类型切换的事情?