Добрый вечер,
начал изучать spring boot, возникла сложность с подключением js, а точнее vue.js. При отправке post, put запросов выдает 403 ошибку (Forbidden).
Также использую шаблонизатор thymeleaf, через отправку форм с теми же запросами всё ок.
Еще хотел бы добавить, что запросы отправляются на другой url (со страницы ./sms.html на ./message), возможно как-то влияет.
В сети искал решение вопроса, натолкнулся на несколько решений, но ни одно из них не сработало, возможно вставлял не в те места.
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/vue-resource@1.5.1"></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: [],
}
});
Просьба помочь разобраться, ещё нашел решение в виде такого пакета:
https://www.npmjs.com/package/vue-csrf. Но пока не стал его использовать, т.к. не хотелось бы пока что касаться сборщиков (npm, yarn).
Был бы рад примеру с готовых проектов, где csrf настроен и работает со спрингом.