我正在尝试使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/