Java configと共にspring securityを使用しています
@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());
RESTサービスのテストにPostManを使用しています。 「csrfトークン」を正常に取得し、リクエストヘッダーで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();
}
}
注: CSRF保護は、Java構成でデフォルトで有効になっています
これを試してください:@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トークンを自動的に生成し、副作用(PUT, POST, PATCH, DELETE).
を持つすべてのHTTPリクエストにそれを含める必要があります
Postmanでは、各リクエストでテストを使用して、CSRFトークンをグローバルに保存できます。 CookieCsrfTokenRepository
を使用する場合
pm.globals.set("xsrf-token", postman.getResponseCookie("XSRF-TOKEN").value);
そして、キーX-XSRF-TOKEN
と値{{xsrf-token}}
を持つヘッダーとしてそれを含めます。
POSTメソッドで同じエラーが発生し、「セッションが見つからなかったため、提供されたCSRFトークンを検証できませんでした」という403 Forbiddenが発生していました。
@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();
}
}
JS fetch AJAXをHTTP Status 403 - Could not verify the provided CSRF token because your session was not found.
オプションを使用せずに呼び出すと、このエラーメッセージ(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保護を有効にすると、アプリケーションに無駄なコードが導入されるだけで、スキップする必要があると思います。
お役に立てれば。