'How does Spring (Spring Boot) provide CSRF token to frontend?
I am trying to add CSRF protection to a project which is based on Spring-Boot (particularly WebFlux).
What I have tried so far is below security configuration.
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.
...
.and()
.csrf()
.csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.requireCsrfProtectionMatcher(
new NegatedServerWebExchangeMatcher(
new OrServerWebExchangeMatcher(
Arrays.asList(
ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, FORM_LOGIN_URL),
ServerWebExchangeMatchers
.pathMatchers(HttpMethod.GET, PERMISSION_ENDPOINT)
)
)
)
)
.accessDeniedHandler(new CustomHttpStatusServerAccessDeniedHandler(HttpStatus.FORBIDDEN))
...;
return http.build();
}
But when I tried above configuration, I could not see anything related to a CSRF token being pushed from server to browser. Is it not by default being pushed to clients? If so what would be the cleaner way to provide CSRF token to client (browser)? In which spring document this is mentioned. (I followed this one -> https://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html)
P.S. (hoping these following information are of any use for an answer)
- My login form is not being served by Spring Boot Webflux application. It is served by a angular application running on a different domain (different IP & Port). That is why I have a
FORM_LOGIN_URLconstant in above configuration, which is used as.loginPage(FORM_LOGIN_URL). I have customized the.authenticationSuccessHandler()to redirect toPERMISSION_ENDPOINTwhich worked as intended up until.
Solution 1:[1]
The contact is static so you don't need overhead of browser.
The easiest approach is to find a pattern e.g. css selector list, which divides the listings into sections you can loop over and extract the desired contact numbers from.
There are a number of css selector lists you could use. A fairly stable one, IMO, would be
.vc_column-inner:has(h3:not(:-soup-contains("Conclusion")))
The :not is to exclude the final Conclusion block.
Once you have your blocks/listings to loop over then you can integrate your current attempt to use :contains or :-soup-contains to extract the numbers
import requests
from bs4 import BeautifulSoup as bs
r = requests.get('https://nigeria.startuphrtoolkit.com/top-startups-in-nigeria', headers = {'User-Agent':'Mozilla/5.0'})
soup = bs(r.content, 'lxml')
sections = soup.select('.vc_column-inner:has(h3:not(:-soup-contains("Conclusion")))')
for section in sections:
print(section.select_one('h3').text)
contact = section.select_one('strong:-soup-contains("Contact")')
if contact is None:
print('No contact number')
else:
print(contact.next_sibling.replace(':', '').strip())
print()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | QHarr |
