草庐IT

angularjs - AngularJS的Gorilla CSRF

coder 2023-06-29 原文

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

有关angularjs - AngularJS的Gorilla CSRF的更多相关文章

  1. ruby-on-rails - 获取 ActionController::RoutingError(当尝试使用 AngularJS 将数据发布到 Rails 服务器时,没有路由匹配 [OPTIONS] "/users" - 2

    尝试从我的AngularJS端将数据发布到Rails服务器时出现问题。服务器错误:ActionController::RoutingError(Noroutematches[OPTIONS]"/users"):actionpack(4.1.9)lib/action_dispatch/middleware/debug_exceptions.rb:21:in`call'actionpack(4.1.9)lib/action_dispatch/middleware/show_exceptions.rb:30:in`call'railties(4.1.9)lib/rails/rack/logg

  2. javascript - angularjs $state 和 $rootScope.$on($stateChangeStart) 问题 - 2

    我已经回答了多个问题,但还没有找到解决方案。我对状态处理有疑问。$urlRouterProvider.otherwise(function($injector,$location){var$state=$injector.get("$state");$state.go("cover");});$stateProvider.state('auth',{url:'/auth',templateUrl:'../views/authView.html',controller:'AuthControllerasauth'}).state('users',{url:'/users',templat

  3. javascript - 在具有静态内容的 angularjs bootstrap 选项卡上处于事件状态 - 2

    我正在使用AngularBootstrapUI来显示带有静态内容的标签集。我对此感到沮丧,因为UIBootstrapTab文档仅显示导航到通过绑定(bind)ng-repeat创建的选项卡。tab1GotoTab3tab2我发现了一些东西听到Stackoverflow但这不适用于当前版本的AngularBootstrapUI..Plunker 最佳答案 要将选项卡设置为事件状态,您需要在范围内将bool标志设置为“true”并将其与给定选项卡的active属性相关联。这看起来像tab1tab2当tabOneActive设置为true

  4. javascript - 结合 AngularJS、jQueryUI、Angular-Drag-Drop 排序列表 - 2

    我遇到以下情况,我需要允许用户从列表中选择对象并将它们拖/放到某个插槽中:对象的大小可以是插槽的一到三倍。所以如果用户将Object1拖到Slot0,那么它只占用Slot0(startSlot=0和endSlot=0)。但是,如果用户将对象3拖动到插槽3,则它会占用插槽3、4和5(startSlot=3和endSlot=5)。将对象放入槽中后,用户可以通过在槽中单击并上下拖动对象来重新排序对象。对象不能相互重叠:我正在使用Angular,所以我正在从数据库中读取对象列表,并且我有一个槽数变量。我尝试了几种解决方案。我相信使用jQuery和jQueryUI可拖动、可放置和可排序是解决方案

  5. javascript - AngularJS 中添加的自定义 header 仅显示在 Access-Control-Request-Headers 上 - 2

    我正在尝试使用拦截器使用以下代码向AngularJS应用程序中的每个请求添加自定义header:angular.module('app').factory('httpRequestInterceptor',function(){return{request:function(config){config.headers['testheader']='testheaderworks';returnconfig;}};});angular.module('app').config(function($httpProvider){$httpProvider.interceptors.push

  6. javascript - 这个 AngularJS 工厂示例究竟是如何工作的?一些疑惑 - 2

    我是AngularJS的新手,我正在学习教程。我对Angular中工厂的使用有疑问。我知道工厂是一种用于根据请求创建对象的模式。所以在例子中有如下代码://Createsvaluesorobjectsondemandangular.module("myApp")//Getthe"myApp"modulecreatedintotheroot.jsfile(intothismoduleisinjectedthe"serviceModule"service.value("testValue","AngularJSUdemy")//Defineafactorynamed"courseFacto

  7. javascript - 带有数据切换的 AngularJS ng-click - 2

    我有一个列表项,它切换模式并使用ng-click设置一个参数问题是在记录Course.SelectedCourse的任何其他地方调用函数时,它是未定义的,尽管Course.ID有一个值。 最佳答案 在Controller中使用一个函数,这可能看起来像这样:在View中:在Controller中functionsetSelectedCourse(course_id){$scope.Course.SelectedCourse=course_id;} 关于javascript-带有数据切换的A

  8. javascript - AngularJS:如何使用 ng-idle - 2

    我目前的情况是:myApp.config(['$routeProvider',function($routeProvider){$routeProvider.when('/home',{templateUrl:'partials/home.html',controller:'homeCtrl'});}这是我当前的.config()我如何将波纹管代码集成到我的上层代码中:.config(function(IdleProvider,KeepaliveProvider){IdleProvider.idle(10*60);//10minutesidleIdleProvider.timeout(

  9. javascript - AngularJS:让元素跟随光标 - 2

    jsfiddle在这里:https://jsfiddle.net/Flignats/jzrzo56u/3/我的页面上有一个最初隐藏的元素(弹出窗口)。当页面上的另一个元素悬停时,我希望弹出窗口显示在光标旁边。在我的fiddle中,我有3个段落和弹出框。当用户的光标进入段落​​时,将显示弹出框。当用户的光标离开该元素时,弹出窗口将不再显示。我在检索光标坐标和将弹出窗口定位在光标附近时遇到问题。感谢任何帮助:)Angular代码:varapp=angular.module('myApp',[]);app.controller('Ctrl',['$scope',function($scope

  10. javascript - 如何在 MVC 中使用 AngularJS 上传文件 - 2

    由于我是AngularJS的新手,我不知道如何使用AngularJS在MVC中上传文件。我试图上传一些没有任何特定类型或扩展名的文件,但失败了。我创建了一个javascript文件,其中有-这是serviceJS-varapp=angular.module("app",[]);app.service('FileUploadService',['$http',function($http){this.uploadFileToUrl=function(file,uploadUrl){varfd=newFormData();fd.append('file',file);$http.post(

随机推荐