9
9
package org .seedstack .seed .web .security .internal ;
10
10
11
11
import java .security .SecureRandom ;
12
+ import java .util .List ;
12
13
import javax .servlet .ServletRequest ;
13
14
import javax .servlet .ServletResponse ;
14
15
import javax .servlet .http .Cookie ;
@@ -35,56 +36,83 @@ protected boolean onPreHandle(ServletRequest request, ServletResponse response,
35
36
HttpServletRequest httpServletRequest = (HttpServletRequest ) request ;
36
37
HttpServletResponse httpServletResponse = (HttpServletResponse ) response ;
37
38
final HttpSession session = httpServletRequest .getSession (false );
38
- final boolean noCheck ;
39
- if (mappedValue != null && ((String []) mappedValue ).length != 0 ) {
40
- noCheck = NO_CHECK .equals (((String []) mappedValue )[0 ]);
41
- } else {
42
- noCheck = false ;
43
- }
44
39
45
40
// Only apply XSRF protection when there is a session
46
41
if (session != null ) {
47
42
// If session is new, generate a token and put it in a cookie
48
43
if (session .isNew ()) {
49
44
setXsrfCookie (httpServletResponse );
50
45
}
51
- // Else, if noCheck is NOT set, check if the request and cookie tokens match
52
- else if (!noCheck ) {
53
- String cookieToken = extractCookieToken (httpServletRequest );
54
- String requestToken = httpServletRequest .getHeader (xsrfConfig .getHeaderName ());
55
-
56
- if (requestToken == null ) {
57
- ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
58
- "Missing CSRF protection token in the request headers" );
59
- return false ;
46
+ // Else, apply XSRF protection logic
47
+ else {
48
+ final boolean noCheck ;
49
+ if (mappedValue != null && ((String []) mappedValue ).length != 0 ) {
50
+ noCheck = NO_CHECK .equals (((String []) mappedValue )[0 ]);
51
+ } else {
52
+ noCheck = false ;
60
53
}
61
54
62
- if (cookieToken == null ) {
63
- ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
64
- "Missing CSRF protection token cookie" );
65
- return false ;
55
+ if (!noCheck && !isRequestIgnored (httpServletRequest )) {
56
+ String cookieToken = getTokenFromCookie (httpServletRequest );
57
+
58
+ // If no cookie is available, send an error
59
+ if (cookieToken == null ) {
60
+ ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
61
+ "Missing CSRF protection token cookie" );
62
+ return false ;
63
+ }
64
+
65
+ // Try to obtain the request token from a header
66
+ String requestToken = getTokenFromHeader (httpServletRequest );
67
+
68
+ // Fallback to query parameter if we didn't a token in the headers
69
+ if (requestToken == null ) {
70
+ requestToken = getTokenFromParameter (httpServletRequest );
71
+ }
72
+
73
+ // If no request token available, send an error
74
+ if (requestToken == null ) {
75
+ ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
76
+ "Missing CSRF protection token in the request headers" );
77
+ return false ;
78
+ }
79
+
80
+ // If tokens don't match, send an error
81
+ if (!cookieToken .equals (requestToken )) {
82
+ ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
83
+ "Request token does not match session token" );
84
+ return false ;
85
+ }
86
+
87
+ // Regenerate token if per-request tokens are in use
88
+ if (xsrfConfig .isPerRequestToken ()) {
89
+ setXsrfCookie (httpServletResponse );
90
+ }
66
91
}
92
+ }
93
+ }
94
+ return true ;
95
+ }
67
96
68
- // Check for multiple headers (keep only the first one)
69
- int commaIndex = requestToken .indexOf (',' );
70
- if (commaIndex != -1 ) {
71
- requestToken = requestToken .substring (0 , commaIndex ).trim ();
72
- }
97
+ protected boolean isRequestIgnored (HttpServletRequest httpServletRequest ) {
98
+ List <String > ignoreHttpMethods = xsrfConfig .getIgnoreHttpMethods ();
99
+ return ignoreHttpMethods != null && ignoreHttpMethods .contains (httpServletRequest .getMethod ());
100
+ }
73
101
74
- // Check if tokens match
75
- if (!cookieToken .equals (requestToken )) {
76
- ((HttpServletResponse ) response ).sendError (HttpServletResponse .SC_FORBIDDEN ,
77
- "Request token does not match session token" );
78
- return false ;
79
- }
102
+ protected String getTokenFromParameter (HttpServletRequest httpServletRequest ) {
103
+ return httpServletRequest .getParameter (xsrfConfig .getParamName ());
104
+ }
80
105
81
- // Regenerate token if per-request tokens are in use
82
- if (xsrfConfig .isPerRequestToken ()) {
83
- setXsrfCookie (httpServletResponse );
84
- }
106
+ protected String getTokenFromHeader (HttpServletRequest httpServletRequest ) {
107
+ String header = httpServletRequest .getHeader (xsrfConfig .getHeaderName ());
108
+ if (header != null ) {
109
+ int commaIndex = header .indexOf (',' );
110
+ if (commaIndex != -1 ) {
111
+ // If header is multi-valued, only keep the first one
112
+ header = header .substring (0 , commaIndex ).trim ();
85
113
}
86
114
}
87
- return true ;
115
+ return header ;
88
116
}
89
117
90
118
protected void postHandle (ServletRequest request , ServletResponse response ) {
@@ -117,7 +145,7 @@ protected void deleteXsrfCookie(HttpServletResponse httpServletResponse) {
117
145
httpServletResponse .setHeader (SET_COOKIE_HEADER , cookieSpec );
118
146
}
119
147
120
- protected String extractCookieToken (HttpServletRequest httpServletRequest ) {
148
+ protected String getTokenFromCookie (HttpServletRequest httpServletRequest ) {
121
149
String cookieName = xsrfConfig .getCookieName ();
122
150
for (Cookie cookie : httpServletRequest .getCookies ()) {
123
151
if (cookieName .equals (cookie .getName ())) {
0 commit comments