在Spring Security取得目前的CsrfToken
物件的方法如下。
CsrfToken
物件可透過HttpServletRequest
物件的attribute
以名稱"_csrf"
取得。
Spring Security產生的CsrfToken
預設是在HttpSessionCsrfTokenRepository.generateToken()
產生的DefaultCsrfToken
物件,預設的request attribute參數名稱定義在HttpSessionCsrfTokenRepository
內的DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
,此外也會以CsrfToken.class.getName()
取得的名稱"CsrfToken"
存放在request attributes。
上述過程請見CsrfFilter.doFilterInternal()
。
所以可以從HttpServletRequest
物件以下面兩種方式取得。
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
或從HttpSession
取得。
CsrfToken token = (CsrfToken) session.getAttribute("HttpSessionCsrfTokenRepository.CSRF_TOKEN");
例如在Spring Security驗證成功後,在自訂的驗證成功處理器DemoAuthenticationSuccessHandler
中由HttpServletRequest
取得CsrfToken
,然後將token值放入response送出。
DemoAuthenticationSuccessHandler
package com.abc.demo.config;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CsrfToken;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DemoAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf"); // get CsrfToken
Map<String, String> data = Collections.singletonMap("csrf_token", csrfToken.getToken());
ObjectMapper objectMapper = new ObjectMapper();
response.getOutputStream().println(objectMapper.writeValueAsString(data));
}
}
回傳的response body的結果。
{"csrf_token":"f172c4e9-bc97-4eca-9fbc-1df9c4c70268"}
如果CsrfToken總是null,那可能Spring Security的csrf停用了,也就是把HttpSecurity.csrf().disable()
。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // <-- 無法取得CsrfToken。
}
在傳統的xml設定則是如下。
<http>
...
<csrf disabled="true"/>
</http>
參考:
沒有留言:
張貼留言