【发布时间】:2015-11-20 10:45:30
【问题描述】:
我对如何进行 CSRF 保护感到困惑。我有单独的前端(angularjs)和后端(Spring)。它们部署在完全不同的地方,并通过 REST 进行通信。
我的问题如下。 Angular 拒绝跨域发送我的 CSRF cookie - 我只能发送 CSRF 标头。我尝试将withCredentials 添加到后端的角度和CORS 过滤器中,并按照here under Usage 的描述设置xsrf 标头和cookie。
任何想法我可能做错了什么?如果您想要我的代码的某些特定部分,请发布,我会提供。
@添加相关代码:
CORS过滤器
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 是的
-
您是否在后端正确配置了
Access-Control-Allow-Origin标头?您可以在后端和前端部分共享代码块相关部分。这样人们就可以检查问题。 -
@İlkerKorkut 我已经添加了相关代码
标签: javascript java angularjs spring cookies