I'm trying to secure my website using Spring Security following the guides on the web.
So on my server side I have the following classes.
My WebSecurityConfigurerAdapter
:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationContextAware {
@Override
protected void registerAuthentication(AuthenticationManagerBuilde rauthManagerBuilder) throws Exception {
authManagerBuilder.inMemoryAuthentication().withUser("user").password("password").roles("ADMIN");
}
}
My controller:
@Controller
//@RequestMapping("/course")
public class CourseController implements ApplicationContextAware {
@RequestMapping(value="/course", method = RequestMethod.GET, produces="application/json")
public @ResponseBody List<Course> get( // The criterion used to find.
@RequestParam(value = "what", required = true) String what,
@RequestParam(value = "value", required = true) String value) {
//.....
}
@RequestMapping(value = "/course", method = RequestMethod.POST, produces = "application/json")
public List<Course> upload(@RequestBody Course[] cs) {
}
}
What confused me very much is the server does not respond to the POST
/ DELETE
method, while the GET
method works fine. BTW, I'm using RestTemplate
on the client side.
Exceptions are:
Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:574)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:530)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:487)
at org.springframework.web.client.RestTemplate.delete(RestTemplate.java:385)
at hello.Application.createRestTemplate(Application.java:149)
at hello.Application.main(Application.java:99)
I've searched the inte.net for days. Still don't have a clue. Please help. Thanks so much
The issue is likely due to CSRF protection . If users will not be using your application in a web browser, then it is safe to disable CSRF protection. Otherwise you should ensure to include the CSRF token in the request .
To disable CSRF protection you can use the following:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter implements ApplicationContextAware {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.csrf().disable();
}
@Override
protected void registerAuthentication(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder
.inMemoryAuthentication()
.withUser("user").password("password").roles("ADMIN");
}
}
The issue may be related to CSRF or CORS Security Protection.
The below code disable CSRF and allow all origins and HTTP methods. so be aware when using it.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}
The issue is likely due to CSRF protection, agree with the top comment. Nevertheless, by using this configuration, the method cancells the spring security.
So you can use the following code:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth
.inMemoryAuthentication()
.withUser("admin")
.password(encoder.encode("admin"))
.roles("ADMIN", "USER")
.and()
.withUser("user")
.password(encoder.encode("password"))
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
http.csrf().disable();
}
}
I've been looking for days too! Simply disabling CSRF on your configure method with http.csrf().disable(); is all that needed to be done for my put requests to stop receiving 403.
Check your token which you are sending through 'Header' and also query in your database for the same token whether that token exist or not.
Note : The above is applicable only in case you are using Spring Boot token authentication mechanism.
I'm posting this in case someone else finds it useful in the future. I spent hours looking for what was failing and finally I find the solution, on Postman making a POST to http://localhost:8080/login/ is not the same as making a POST to http://localhost:8080/login (with "/" at the end of request it will return 403 forbidden)
I had this problem after upgrading my service to Spring Boot 3. Automatic tests started to fail with a 403 status. After quite a lot of headaches, I found out it is caused by removing trailing slash from URL matching. The change is described here. So check that you are calling the correct URL.
Wrong:
/api/foo/
Right:
/api/foo
http.httpBasic().disable();
http.authorizeRequests().antMatchers("/signup").permitAll().antMatchers("/*")
.fullyAuthenticated().and().formLogin()
.and().csrf().disable();
http.csrf().disable();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.