84 lines
1.8 KiB
Markdown
84 lines
1.8 KiB
Markdown
|
# CSRF protection
|
||
|
|
||
|
A golang library that implements CSRF protection.
|
||
|
|
||
|
|
||
|
## Implementation
|
||
|
|
||
|
This library sets a cookie with a random token.
|
||
|
Every unsafe request (POST, PUT, DELETE, etc.) must contain a copy of this token in a form field or HTTP header.
|
||
|
|
||
|
|
||
|
## Usage
|
||
|
|
||
|
```go
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
|
||
|
"code.app-house.ru/app-house/csrf"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
r := http.NewServeMux()
|
||
|
csrfProtection := csrf.New()
|
||
|
|
||
|
// You can change field or header name (as well as other settings):
|
||
|
// csrfProtection.FormFieldName = "foo"
|
||
|
// csrfProtection.HeaderName = "bar"
|
||
|
|
||
|
http.ListenAndServe(":8000", csrfProtection.Middleware(r))
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Option 1: add a hidden input to all forms that use unsafe methods:
|
||
|
|
||
|
```html
|
||
|
<input type="hidden" name="{{ .CsrfFieldName }}" value="{{ .CsrfToken }}" />
|
||
|
```
|
||
|
|
||
|
Your HTTP handler may look like this:
|
||
|
|
||
|
```go
|
||
|
template.Execute(w, yourViewModel{
|
||
|
CsrfFieldName: csrfProtection.FieldName,
|
||
|
CsrfToken: csrf.GetCSRFToken(r.Context()),
|
||
|
})
|
||
|
```
|
||
|
|
||
|
Option 2: provide a token using JavaScript:
|
||
|
|
||
|
```javascript
|
||
|
/**
|
||
|
* Copied from https://docs.djangoproject.com/en/5.2/howto/csrf/.
|
||
|
* @param {string} name - Cookie name.
|
||
|
* @returns {string | null}
|
||
|
*/
|
||
|
function getCookie(name) {
|
||
|
let cookieValue = null;
|
||
|
if (document.cookie && document.cookie !== "") {
|
||
|
const cookies = document.cookie.split(";");
|
||
|
for (let i = 0; i < cookies.length; i++) {
|
||
|
const cookie = cookies[i].trim();
|
||
|
// Does this cookie string begin with the name we want?
|
||
|
if (cookie.substring(0, name.length + 1) === name + "=") {
|
||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return cookieValue;
|
||
|
}
|
||
|
|
||
|
async function makeRequest() {
|
||
|
const csrfToken = getCookie("csrfmiddlewaretoken");
|
||
|
await fetch("/handler", {
|
||
|
method: "POST",
|
||
|
headers: {
|
||
|
"X-CSRFToken": csrfToken,
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
```
|