问题
Following the sample from Spring Boot: example code from GitHub everything seems to work fine.
But when I integrate Spring Boot Security OAuth2 in the project, my OAuth2 endpoints stop working. There's a warning in the logs:
2017-05-04 08:56:24.109 WARN 2827 --- [nio-8080-exec-1] o.glassfish.jersey.servlet.WebComponent : A servlet request to the URI http://127.0.0.1:8080/oauth/token contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
Which makes me think even though I'm not registering the endpoint, Jersey is capturing it and processing the body, making Spring MVC unable to accept the request...
My Jersey Config is:
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(InfoController.class);
}
}
And my info controller is very simple:
@Component
@Path("/me")
@Produces("application/json")
public class InfoController {
@GET
public String meAction() {
return "Hi";
}
}
And finally, the call I'm trying to make and it's causing the warning in the logs:
curl -X POST -u CLIENT_APPLICATION:123456789 http://127.0.0.1:8080/oauth/token -H "Accept: application/json" -d "password=aaa&username=aa&grant_type=password&client_id=CLIENT_APPLICATION"
Is there a known incompatibility between the two projects (spring-boot-starter-jersey
and spring-security-oauth2
in that sense?
Removing the Jersey configuration makes it all work, but I need to use it on my controllers.
My configuration for OAuth2 is:
@Configuration
public class OAuth2ServerConfiguration {
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("OAuth2 Server");
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/*").authenticated();
// @formatter:on
}
}
}
Then there's the security configuration itself:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ApiUserDetailsService userDetailsService;
@Autowired
public WebSecurityConfiguration(ApiUserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Thanks in advance!
回答1:
It seems that Jersey is trying the handle the OAuth endpoint, which it shouldn't be. The reason is that the default mapping for Jersey is /*
, which means that it will handle requests for all URLs. You can change that in a couple of ways:
Add an
@ApplicationPath
on top of yourResourceConfig
subclass with a different mapping@Component @ApplicationPath("/api") public class JerseyConfig extends ResourceConfig {}
You can add the mapping in your
application.properties
filespring.jersey.application-path=/api
What this will do is prefix /api
to all your Jersey endpoints, and also cause Jersey not to handle all request, only ones that begin with /api
.
来源:https://stackoverflow.com/questions/43777373/spring-boot-with-jersey-and-spring-security-oauth2