在我的应用程序中启用了csrf(删除行.csrf().disable()
)后,我的登录请求停止了工作 - /login
POST
将我重定向到主页:
在页面上我跟随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
我尝试将其直接添加到表单中:
再没有成功。
另外我试过这个:
但是你可以看到 - 它也没有解决我的属性
配置:
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);
}
});
}
}
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")
}
答案 0 :(得分:0)
尝试直接将此输入添加到表单(而不是使用jQuery):
<form>
<!-- all the rest inputs -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
如果您通过AJAX将数据发送到服务器,则可以从<meta>
获取这些值。
$(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);
});
});
如果您需要在Cookie中保留CsrfToken
,默认情况下CookieCsrfTokenRepository
会写入名为XSRF-TOKEN
的Cookie,并从名为{{1}的标头中读取它或HTTP参数X-XSRF-TOKEN
。
答案 1 :(得分:0)
我尝试了不同的方法,最终我找到了解决方案:
以前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
之类的值插入变量,那么在th:content="${_csrf.token}"
原始html中查看spring boot搜索。