Я смущенно о том, как мне сделать защиту CSRF. У меня есть отдельный интерфейс (angularjs) и backend (Spring). Они развернуты в совершенно разных местах и сообщают REST.Двойная передача CSRF защита кросс-домена
Моя проблема заключается в следующем. Угловой отказывается отправлять мой домен CSRF cookie - все, что я могу отправить, это заголовок CSRF. Я попытался добавить withCredentials
как к угловому, так и к фильтрам CORS на моем бэкэнд и настройке заголовка xsrf и файла cookie, как описано here under Usage.
Любые идеи, что я могу делать неправильно? Если вам нужна определенная часть моего кода, отправьте сообщение, и я поставлю его.
@Adding соответствующий код:
CORSFilter
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9000");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,origin,content-type,accept,X-XSRF-TOKEN, authorization, customer-id, X-AUTH-TOKEN");
response.setHeader("Access-Control-Expose-Headers", "employee_name, employee_id, employee_customer_id, X-AUTH-TOKEN");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
if (request.getMethod()!="OPTIONS") {
chain.doFilter(req, res);
} else {
}
}
CSRF фильтр
public class StatelessCSRFFilter extends OncePerRequestFilter {
private static final String CSRF_TOKEN = "CSRF-TOKEN";
private static final String X_CSRF_TOKEN = "X-XSRF-TOKEN";
private final RequestMatcher requireCsrfProtectionMatcher = new DefaultRequiresCsrfMatcher();
private final AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (requireCsrfProtectionMatcher.matches(request)) {
final String csrfTokenValue = request.getHeader(X_CSRF_TOKEN);
final Cookie[] cookies = request.getCookies();
String csrfCookieValue = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(CSRF_TOKEN)) {
csrfCookieValue = cookie.getValue();
}
}
}
if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {
accessDeniedHandler.handle(request, response, new AccessDeniedException(
"Missing or non-matching CSRF-token"));
return;
}
}
filterChain.doFilter(request, response);
}
public static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
private final Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
@Override
public boolean matches(HttpServletRequest request) {
return !allowedMethods.matcher(request.getMethod()).matches();
}
}
app.js
(...)
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
$httpProvider.defaults.xsrfCookieName = 'CSRF-TOKEN';
$httpProvider.interceptors.push('InterceptorCsrf');
$httpProvider.defaults.withCredentials = true;
(...)
InterceptorCsrf.js
angular.module('EnterprisePortalApp')
.factory('InterceptorCsrf',function($cookies, $cookieStorage){
function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e16]+1e16).replace(/[01]/g,b)};
return {
//With each request generate new csrf token
request: function(config) {
$cookieStorage.put("CSRF-TOKEN", b());
config.headers['X-XSRF-TOKEN'] = $cookies.get('CSRF-TOKEN');
return config;
}
}
});
Не могли бы вы рассказать о том, что вы имеете в виду, говоря, что они развернуты в совершенно разных местах? Это на разных серверах? –
@MicheleRicciardi Yup –
Вы правильно настроили заголовок 'Access-Control-Allow-Origin' на своем сервере? Вы можете делиться блоками, связанными с блоками, как с базовыми, так и с внешними разделами. Поэтому люди могут проверять проблемы. –