A
A
Alexey2019-12-07 23:22:49
Spring
Alexey, 2019-12-07 23:22:49

How to enable CSRF token in vue.js + spring?

Good evening,
I started to study spring boot, there was a difficulty with connecting js, or rather vue.js. When sending post, put requests, it gives a 403 error (Forbidden).
I also use the thymeleaf template engine, through sending forms with the same requests everything is ok.
I would also like to add that requests are sent to a different url (from the page ./sms.html to ./message), perhaps somehow affects.
I searched the network for a solution to the issue, came across several solutions, but none of them worked, maybe I inserted it in the wrong places.
sms.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3" lang="en">
    <head>
        <meta charset="UTF-8">
        <title>web service</title>
        <!-- development version, includes helpful console warnings -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

        <meta name="csrf-token" content="{{ csrf_token() }}">

        <meta name="_csrf" content="${_csrf.token}"/>
        <meta name="_csrf_header" content="${_csrf.headerName}"/>

    </head>
    <body>
        <h3>web service</h3>
            <div id="app">
                <p>{{ csrf_field() }}</p>
                <p>{{ message }}</p>
            </div>
            <script src="/js/main.js">{{ csrf_field() }}</script>
            <input type="hidden" name="_token" :value="csrf">

    </body>
</html>

main.js:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
    xhr.setRequestHeader(header, token);
});

function getIndex(list, id) {
    for (var i = 0; i < list.length; i++ ) {
        if (list[i].id === id) {
            return i;
        }
    }

    return -1;
}

var messageApi = Vue.resource('/message{/id}');

Vue.component('message-form', {
    props: ['messages', 'messageAttr'],
    data: function() {
        return {
            text: '',
            id: ''
        }
    },
    watch: {
        messageAttr: function(newVal, oldVal) {
            this.text = newVal.text;
            this.id = newVal.id;
        }
    },
    template:
        '<div>' +
        '<input type="text" placeholder="Write something" v-model="text" />' +
        '<input type="button" value="Save" @click="save" />' +
        '</div>',
    methods: {
        save: function() {
            var message = { text: this.text };

            if (this.id) {
                messageApi.update({id: this.id}, message).then(result =>
                    result.json().then(data => {
                        var index = getIndex(this.messages, data.id);
                        this.messages.splice(index, 1, data);
                        this.text = '';
                        this.id = ''
                    })
                )
            } else {
                messageApi.save({}, message).then(result =>
                    result.json().then(data => {
                        this.messages.push(data);
                        this.text = ''
                    })
                )
            }
        }
    }
});

Vue.component('message-row', {
    props: ['message', 'editMethod', 'messages'],
    template: '<div>' +
        '<i>({{ message.id }})</i> {{ message.text }}' +
        '<span style="position: absolute; right: 0">' +
        '<input type="button" value="Edit" @click="edit" />' +
        '<input type="button" value="X" @click="del" />' +
        '</span>' +
        '</div>',
    methods: {
        edit: function() {
            this.editMethod(this.message);
        },
        del: function() {
            messageApi.remove({id: this.message.id}).then(result => {
                if (result.ok) {
                    this.messages.splice(this.messages.indexOf(this.message), 1)
                }
            })
        }
    }
});

Vue.component('messages-list', {
    props: ['messages'],
    data: function() {
        return {
            message: null
        }
    },
    template:
        '<div style="position: relative; width: 300px;">' +
        '<message-form :messages="messages" :messageAttr="message" />' +
        '<message-row v-for="message in messages" :key="message.id" :message="message" ' +
        ':editMethod="editMethod" :messages="messages" />' +
        '</div>',
    created: function() {
        messageApi.get().then(result =>
            result.json().then(data =>
                data.forEach(message => this.messages.push(message))
            )
        )
    },
    methods: {
        editMethod: function(message) {
            this.message = message;
        }
    }
});

var app = new Vue({
    el: '#app',
    template: '<messages-list :messages="messages" />',
    data: {
        messages: [],
    }
});

Please help me figure it out, I also found a solution in the form of such a package: https://www.npmjs.com/package/vue-csrf. But so far I haven’t started using it, because. I would not like to touch the assemblers (npm, yarn) for the time being.
I would be happy with an example from ready-made projects where csrf is configured and works with spring.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Orkhan Hasanli, 2019-12-07
@zeroWiNNeR

Hello!
I didn't have to work specifically with Vue.JS, but I came across a case where you need to use a CSRF token with JS (jquery, etc.).
Here are the links that helped me at the time:
https://www.codesandnotes.be/2015/02/05/spring-sec...
Pay attention to the
Handling CSRF tokens on the client side
https://www. baeldung.com/csrf-thymeleaf-with-sprin...
https://stackoverflow.com/questions/37383730/how-t...
https://www.baeldung.com/spring-security-csrf
https:/ /stackoverflow.com/questions/33125598/how-t...
https://stackoverflow.com/questions/48985293/sprin...
https://blog.netgloo.com/2014/09/28/spring-boot -en...
Hope these links will help you too.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question