![](/img/trans.png)
[英]MissingCsrfTokenException: Could not verify the provided CSRF token because your session was not found
[英]Could not verify the provided CSRF token because your session was not found in spring security
我正在使用spring security和java config
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/*").hasRole("ADMIN")
.and()
.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler());
我正在使用PostMan來測試我的REST服務。 我成功獲得'csrf token',我可以在請求標頭中使用X-CSRF-TOKEN
登錄。 但登錄后我點擊發布請求(我在請求標題中包含相同的令牌,我用於登錄發布請求)我收到以下錯誤消息:
HTTP狀態403 - 無法驗證提供的CSRF令牌,因為找不到您的會話。
任何人都可以指導我做錯了什么。
根據spring.io:
什么時候應該使用CSRF保護? 我們的建議是對普通用戶可以由瀏覽器處理的任何請求使用CSRF保護。 如果您只創建非瀏覽器客戶端使用的服務,則可能需要禁用CSRF保護。
所以要禁用它:
@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
注意: Java配置默認啟用CSRF保護
試試這個: @Override protected boolean sameOriginDisabled() { return true;}
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
...
// Determines if a CSRF token is required for connecting. This protects against remote
// sites from connecting to the application and being able to read/write data over the
// connection. The default is false (the token is required).
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
禁用CSRF保護是個壞主意。
Spring會在每次請求后自動生成一個新的CSRF令牌,您需要將它包含在帶有副作用的所有HTTP請求中(PUT, POST, PATCH, DELETE).
在Postman中,您可以在每個請求中使用測試將CSRF令牌存儲在全局中,例如在使用CookieCsrfTokenRepository
pm.globals.set("xsrf-token", postman.getResponseCookie("XSRF-TOKEN").value);
然后將其作為帶有鍵X-XSRF-TOKEN
和值{{xsrf-token}}
的標題包含{{xsrf-token}}
。
獲得了與POST方法相同的錯誤,獲得了403 Forbidden“無法驗證提供的CSRF令牌,因為找不到您的會話。”
通過在配置中添加@EnableResourceServer注釋來探索一段時間后找到解決方案。
Config看起來像那樣(spring-boot.version - > 1.4.1.RELEASE,spring-security.version - > 4.1.3.RELEASE,spring.version - > 4.3.4.RELEASE)
@Configuration
@EnableWebSecurity
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends ResourceServerConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inMemoryUserDetailsManager()).passwordEncoder(passwordEncoder());
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.sessionManagement().sessionCreationPolicy(STATELESS);
http.csrf().disable();
http.authorizeRequests().anyRequest()
.permitAll();
}
private InMemoryUserDetailsManager inMemoryUserDetailsManager() throws IOException {
// load custom properties
Properties properties = new Properties();
return new InMemoryUserDetailsManager(properties);
}
private PasswordEncoder passwordEncoder() {
return new TextEncryptorBasedPasswordEncoder(textEncryptor());
}
private TextEncryptor textEncryptor() {
return new OpenSslCompatibleTextEncryptor();
}
}
我收到此錯誤消息( HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.
)當我在不使用credentials: "same-origin"
執行JS 獲取 AJAX調用時credentials: "same-origin"
選項。
錯誤的方法
fetch(url)
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })
正確的方式
fetch(url, {
credentials: "same-origin"
})
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })
這是一個老問題,但這可能對某人有所幫助。 我有類似的問題,這就是我能夠解決它的方式。
為了使CSRF能夠與REST API一起使用,您需要在每次調用之前通過API獲取CSRF令牌並使用該令牌。 令牌每次都不同,不能重復使用。
以下是獲取CSRF令牌的控制器:
@RequestMapping(value = "/csrf", method = RequestMethod.GET)
public ResponseEntity<CSRFDTO> getCsrfToken(HttpServletRequest request) {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
return ResponseEntity.ok(CSRFDTO.builder()
.headerName(csrf.getHeaderName())
.token(csrf.getToken())
.build());
}
此外,您可以考慮配置Spring應用程序以禁用REST API端點的CSRF。 引用我在某處讀過的文章:
我非常確定REST端點上的CSRF令牌可以提供額外的保護。 因此,在REST端點上啟用CSRF保護只會為您的應用程序引入一些無用的代碼,我認為應該跳過它。
希望這可以幫助。
我已經通過在我的登錄頁面中添加最后一個屬性來解決它,也許它會幫到你。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"%>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.