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 internet for days. Still don’t have a clue. Please help. Thanks so much
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Assignees
Comments
Summary
When I try to POST to a resource requiring authentication, I am redirected to a login page (as expected). Upon entering the username and password, I get a 403 access denied error. This works fine if I do a GET to the exact same resource. It’s only for a POST.
Actual Behavior
Receive 403 after successful authentication if authentication trigger is a POST to a protected resource.
Expected Behavior
Resource call should execute same as a GET.
Configuration
@OverRide
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(«//action/«).access(«isFullyAuthenticated()»)
.and().formLogin()
.and().csrf().disable();
Version
Tried 5.0.4 and 4.2.4
Sample
@bleepbleepbleep, the behavior you specify is already supported:
@SpringBootApplication public class DemoApplication { @Controller public static class ActionController { @GetMapping("/action") @ResponseBody String getOk() { return "<form action='/action' method='post'><button type='submit'>Go</button></form>"; } @PostMapping("/action") @ResponseBody String postOk() { return "ok"; } } @EnableWebSecurity public static class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/action/**") .access("isFullyAuthenticated()") .and() .formLogin() .and() .csrf().disable(); } @Bean @Override public UserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build() return new InMemoryUserDetailsManager(user); } } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
In the above code, both GET /action and POST /action return a 200 OK once the user is authenticated.
Note the ant syntax for /action, which is where I think I could be misunderstanding your use case. Would you mind clarifying if you feel I’ve misunderstood? Otherwise, I’ll close this issue and recommend that you make a post to StackOverflow for further troubleshooting support.
@bleepbleepbleep From your statement GET works well and POST throws 403 error, I suspect that CSRF protect is enabled and the post request doesn’t include a valid csrf token.
But your sample code states that csrf is disabled, can you confirm the same from your application configuration to make sure that csrf is disabled?
this is something I am facing right now with spring security 5.1.5
@charlie39 would you be able to provide a sample project that reproduces the issue you are experiencing?
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Has anyone fixed this error?
I’m facing this issue when I trigger a POST request with couple of fields.
{
«timestamp»: «2020-02-06T19:58:23.636+0000»,
«status»: 403,
«error»: «Forbidden»,
«message»: «Access Denied»,
«path»: «/csor/security/greet»
}
I have CSRF disabled in security config as below:
@OverRide
public void configure(HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// .antMatchers(«csor/security/authenticate/»).permitAll()
.antMatchers(«/v2/api-docs»,
«/swagger-resources/«,
«/swagger-ui.html»,
«/webjars/«
).permitAll()
// .anyRequest().authenticated()
.and()
.csrf().disable();
//.and()
//.addFilter(new JwtAuthenticationFilter(authenticationManager()))
//.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
I’ve been experiencing this issue for the past 1 week now. I disabled csrf but I still get the same error. Any little help would be appreciated.
Im having the same issue.
even i am facing this issue, how to resolve 403 error for POST api
Last Modified 2021.11.29
Add the following to redirect access denied user requests to the /WEB-INF/views/403.jsp page.
security.xml
<http>
<access-denied-handler error-page="/403" />
<intercept-url pattern="/users/bye_confirm" access="permitAll"/>
<intercept-url pattern="/users/welcome" access="permitAll"/>
<intercept-url pattern="/users/signUp" access="permitAll"/>
<intercept-url pattern="/users/login" access="permitAll"/>
<intercept-url pattern="/images/**" access="permitAll"/>
<intercept-url pattern="/css/**" access="permitAll"/>
<intercept-url pattern="/js/**" access="permitAll"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/users/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')"/>
<intercept-url pattern="/bbs/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')"/>
<!-- omit -->
You need to declare a handler for «/403» in the controller with the above configuration. Otherwise, you will get a 404 error.
Create a 403.jsp file and add the following method to your HomeController.
/403.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ page import="net.java_school.user.User" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>403</title>
<link rel="stylesheet" href="/css/screen.css" type="text/css" />
<script type="text/javascript" src="/js/jquery-3.2.1.min.js"></script>
</head>
<body>
<div id="wrap">
<div id="header">
<%@ include file="inc/header.jsp" %>
</div>
<div id="main-menu">
<%@ include file="inc/main-menu.jsp" %>
</div>
<div id="container">
<div id="content" style="min-height: 800px;">
<div id="content-categories">Error</div>
<h1>403</h1>
Access is Denied.
</div>
</div>
<div id="sidebar">
<h1>Error</h1>
</div>
<div id="extra">
<%@ include file="inc/extra.jsp" %>
</div>
<div id="footer">
<%@ include file="inc/footer.jsp" %>
</div>
</div>
</body>
</html>
HomeController.java
@RequestMapping(value="/403", method={RequestMethod.GET,RequestMethod.POST})
public String error403() {
return "403";
}
Exclude 403 error from error page configuration in web.xml.
web.xml
<error-page> <error-code>404</error-code> <location>/WEB-INF/views/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/views/500.jsp</location> </error-page>
Run mvn clean compile war:inplace, rerun Tomcat, and visit http://localhost:8080/admin. If the user has only the ROLE_USER privilege, /WEB-INF/views/403.jsp will be displayed.
Implementing AccessDeniedHandler
If you have business logic to perform before showing the user an error page, you should configure your access denied handler by implementing the org.springframework.security.web.access.AccessDeniedHandler.
Create a MyAccessDeniedHandler that implements AccessDeniedHandler.
MyAccessDeniedHandler.java
package net.java_school.spring;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
public class MyAccessDeniedHandler implements AccessDeniedHandler {
private String errorPage;
public void setErrorPage(String errorPage) {
this.errorPage = errorPage;
}
@Override
public void handle(HttpServletRequest req, HttpServletResponse resp, AccessDeniedException e)
throws IOException, ServletException {
//TODO: business logic
req.getRequestDispatcher(errorPage).forward(req, resp);
}
}
Add the following to security.xml.
security.xml
<beans:bean id="my403" class="net.java_school.spring.MyAccessDeniedHandler">
<beans:property name="errorPage" value="403" />
</beans:bean>
Modify the security.xml file as follows:
security.xml
<access-denied-handler ref="my403" />
The Spring Security tag does not work for error pages set in web.xml because the request is forwarded to these error pages before the view-level security filter works.
Method Security
The simplest way to map an exception to an error page in Spring MVC is to use the SimpleMappingExceptionResolver. The following configuration maps to error-403 when the org.springframework.security.access.AccessDeniedException occurs, and to error when any other exception occurs. The view resolver interprets error-403 and error as /WEB-INF/views/error-403.jsp and /WEB-INF/views/error.jsp respectively.
spring-bbs-servlet.xml
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error" />
<property name="exceptionMappings">
<props>
<prop key="AccessDeniedException">
error-403
</prop>
</props>
</property>
</bean>
After signing up and logging in with janedoe@gmail.org/1111, try to withdraw membership with johndoe@gmail.org/1111 from the Bye menu.
UserService.java
@PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER') and #user.email == principal.username")
public void bye(User user);
The highlighted part above will work and occur an org.springframework.security.access.AccessDeniedException, and you will see /WEB-INF/views/error-403.jsp.
On the Bye page, try to withdraw membership with janedoe@gmail.org and the wrong password.
UserServiceImpl.java
@Override
public void bye(User user) {
String encodedPassword = this.getUser(user.getEmail()).getPasswd();
boolean check = this.bcryptPasswordEncoder.matches(user.getPasswd(), encodedPassword);
if (check == false) {
throw new AccessDeniedException("Wrong password!");
}
userMapper.deleteAuthority(user.getEmail());
userMapper.delete(user);
}
The highlighted part above will occur an org.springframework.security.access.AccessDeniedException, and you will see /WEB-INF/views/error-403.jsp.
