Как добавить токен csrf в HTML-форму? - PullRequest
0 голосов
/ 27 апреля 2018

После того, как я включил csrf (удаленная строка .csrf().disable()) в моем приложении, мой запрос на вход перестал работать - /login POST перенаправляет меня на домашнюю страницу:

запрос выглядит так:
enter image description here

На странице у меня есть следующие js:

<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
...
$('#login-form').submit(function (ev) {
    ev.preventDefault(); // to stop the form from submitting
    var headerName = "X-CSRF-TOKEN";
    var token = Cookies.get('XSRF-TOKEN')
    $('<input>').attr('type', 'hidden').attr('name', '_csrf').attr('value', Cookies.get('XSRF-TOKEN')).appendTo('#login-form');
    this.submit(); // If all the validations succeeded
    })

Можете ли вы уточнить, что я делаю не так?

приписка

Я прочитал много похожих вещей и везде встречал такие строки:

<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>

Я не понимаю, как мне установить значение _csrf.headerName

Я пытался добавить эти данные в мета-бит, который не разрешается:
enter image description here

и я попытался добавить его в форму напрямую:

enter image description here

И снова безуспешно.

Дополнительно я попробовал это:

enter image description here

Но, как вы видите, мои атрибуты тоже не решаются

P.S.2

конфигурация: * +1051 *

EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String SECURE_ADMIN_PASSWORD = "rockandroll";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()
                .loginPage("/index.html")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/sender.html")
                    .permitAll()
                .and()
                .logout()
                    .logoutSuccessUrl("/index.html")
                    .permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/js/**", "/lib/**", "/images/**", "/css/**", "/index.html", "/","/*.css","/webjars/**", "/*.js").permitAll()
                .antMatchers("/websocket").hasRole("ADMIN")
                .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ADMIN")
                .anyRequest().authenticated();

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(new AuthenticationProvider() {

            @Override
            public boolean supports(Class<?> authentication) {
                return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
            }

            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;

                List<GrantedAuthority> authorities = SECURE_ADMIN_PASSWORD.equals(token.getCredentials()) ?
                        AuthorityUtils.createAuthorityList("ROLE_ADMIN") : null;

                return new UsernamePasswordAuthenticationToken(token.getName(), token.getCredentials(), authorities);
            }
        });
    }
}

build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

jar {
    baseName = 'gs-messaging-stomp-websocket'
    version = '0.1.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-websocket")
    compile("org.webjars:webjars-locator-core")
    compile("org.webjars:sockjs-client:1.0.2")
    compile("org.webjars:stomp-websocket:2.3.3")
    compile("org.webjars:bootstrap:3.3.7")
    compile("org.webjars:jquery:3.1.0")
    compile("org.webjars:js-cookie:2.1.0")

    compile("org.springframework.boot:spring-boot-starter-actuator")
    //security
    compile ('org.springframework.security:spring-security-messaging')
    compile group: 'org.springframework.security', name: 'spring-security-web'
    compile group: 'org.springframework.security', name: 'spring-security-config'

    testCompile("org.springframework.boot:spring-boot-starter-test")
}

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Я пробовал разные способы, и в итоге я нашел решение:

Ранее index.html находилось в папке /resources/static

Я положил его в папку /resources/templates. Также я добавил зависимость:

compile('org.thymeleaf:thymeleaf-spring5');

и явно объявил контроллер:

@RequestMapping("/")
public String index(){
   return "index";
} 

index.html выглядит так:

<html lang="en" ng-app="springChat" xmlns:th="http://www.springframework.org/schema/beans">
<head>
    ...
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <meta name="_csrf_parameter_name" th:content="${_csrf.parameterName}"/>

....
</body>     
<script type="application/javascript">

    $('#login-form').submit(function (ev) {
        ev.preventDefault(); // to stop the form from submitting
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameter_name']").attr("content");
        $('<input>').attr('type', 'hidden').attr('name', paramName).attr('value', token).appendTo('#login-form');

        this.submit(); 
    });
</script>
</html>

Похоже на весенний поиск при загрузке в /resources/static raw html, если у нас нет явно объявленного отображения и мы не пытаемся вставить значения, подобные th:content="${_csrf.token}", в переменные.

0 голосов
/ 27 апреля 2018

Попробуйте добавить этот ввод непосредственно в вашу форму (не с помощью jQuery):

<form>
    <!-- all the rest inputs -->

    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>

Если вы отправляете свои данные на сервер через AJAX, вы можете получить эти значения из ваших <meta> s.

$(function () {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");

    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });
});

Если в вашем случае вам нужно сохранить CsrfToken в cookie, по умолчанию CookieCsrfTokenRepository запишет в cookie с именем XSRF-TOKEN и прочитает его из заголовка с именем X-XSRF-TOKEN или параметра HTTP _csrf.

...