CSRF Использование Spring Security для серверных вызовов - PullRequest
0 голосов
/ 29 марта 2019

Я собирался применить защитные меры против CSRF-атаки (используя Spring Security) на моем уже созданном приложении.Однако при разработке подхода я сталкиваюсь со следующими проблемами:

Предположим, у меня есть два API со следующими конечными точками:

  1. / abc
  2. / xyz

Сценарий 1 : Front End вызывает / abc вместе с токеном csrf.Сервер проверяет токен csrf и передает его, если он найден правильным.Это работает нормально.

Сценарий 2 : Front End вызывает / xyz вместе с токеном csrf.Сервер проверяет токен csrf и передает его, если он найден правильным.Это снова работает нормально.

Сценарий 3 : API / abc вызывает API / xyz внутри.Однако API / xyz ожидает токен CSRF, который поступает только из внешнего интерфейса, и, следовательно, / xyz не работает из-за отсутствия токена csrf.

Сценарий 4 : У нас также есть несколько сторонних приложений (например, платежный шлюз), которые используют наши API.Как они передадут токен CSRF нашим API?

По сути, я хочу защитить все наши API от атаки CSRF, но мне трудно передать токен csrf от BE к BE и от шлюза платежей к BE.Пожалуйста, помогите мне завершить подход, которому я должен следовать, чтобы я мог легко охватить все эти 4 сценария и защитить приложение от любой атаки CSRF.

ВОПРОС ОБНОВЛЕНИЯ С ОБРАЗЦАМИ КОДА

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .requireCsrfProtectionMatcher(new RequestMatcher() {

                @Override
                public boolean matches(HttpServletRequest request) {

                    final HashSet<String> allowedMethods = new HashSet<String>(
                            Arrays.asList("GET", "HEAD", "TRACE", "OPTIONS"));
                    boolean methodCheck = allowedMethods.contains(request.getMethod());
                    if(methodCheck) {
                        return false;
                    }
                    return true;
                }
            });
}

}

API

API 1:

@RestController
public class GetVersion {

@RequestMapping(path="/", method=RequestMethod.GET)
public String getVersion() {
    return "This is a Get Call";
}

}

API 2:

@RestController
public class PostCall2 {
    @RequestMapping(value="/{path}/postcall2",method=RequestMethod.POST)
    public String postCall2(@PathVariable("path") String path) {
        return "This is path: "+path;
    }
}

API 3:

@RestController
public class PostCall1 {

@RequestMapping(path="/{path}/postcall1",method=RequestMethod.POST)
@ResponseBody
public String postCall1(@PathVariable("path") String path) {
    System.out.println("Tring to call /postcall2 from /postcall1");

    final String url = "http://localhost:8080/thisisxyz/postcall2";


    RestTemplate restTemplate = new RestTemplate();
    try {
        String result = restTemplate.postForObject(url, "", String.class);
        System.out.println("Result is: "+result);
        System.out.println("Successfully called /postcall2 from /postcall1");
        return "This is path: "+path;
    }
    catch(HTTPException e) {
        e.printStackTrace();
        return "Failed";
    }
    catch(Exception e) {
        e.printStackTrace();
        return "Failed";
    }
}
}

API 1 и API 2 работают нормально, так как их вызывают напрямую.Однако API 3 пытается внутренне вызвать API 2 и не работает, потому что не может предоставить токен CSRF для API 2. Пожалуйста, помогите.

...