我正在开发Spring MVC应用程序,我对发生的情况感到有些困惑。
我提供了2个入口点:
第二个是REST入口点。
我的配置如下:
@Configuration
@EnableWebSecurity
@ComponentScan("com.springapp.mvc")
@Order(1)
public class ApiWebConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private ApplicationAuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole(Role.USER);
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
/*http
.requiresChannel()
.antMatchers("/api*//**")
.requiresSecure();*/
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider)
.authenticationEventPublisher(authenticationEventPublisher())
.eraseCredentials(true);
}
AuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher(new ApiWebApplicationEventPublisher());
}
static final class ApiWebApplicationEventPublisher implements org.springframework.context.ApplicationEventPublisher {
@Override
public void publishEvent(ApplicationEvent event) {
event.getSource(); //just to check while debugging
}
}
}
我的控制器:
@Controller
@RequestMapping(value = "/api",
produces = MediaType.APPLICATION_JSON_VALUE)
class APIController {
@Autowired
private MeetingsService meetingsService;
@RequestMapping(value="/meetings/{id}",
method= RequestMethod.GET,
headers = {"Content-type=application/json"})
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public Meeting returnMeetingByIdOrEmpty(@PathVariable("id") final Long id) {
try {
final Meeting meeting = meetingsService.findById(id).get();
return meeting;
} catch (RuntimeException e) {
return null;
}
}
}
我正在使用Spring 4.0.0.RELEASE,Spring Security 3.2.4.RELEASE。
cUrl请求:
curl -i -GET -u my.user:password -H 'Accept: application/json' http://localhost:8080/api/meetings/9
在回复中,我获得了HTTP 403代码的默认html页面内容。
HTTP 403表示用户已通过身份验证,但没有必要的权限来请求内容。
但是,我的用户拥有权限USER,使他有权获取内容。
我希望使用JSON内容获得200 - OK状态。
我的配置中遗漏了什么?
我在某个地方犯了错误吗?
有人可以澄清如何使用安全性成功创建RESTful服务吗?
SOLUTION:
好的,基本上我忘记了正确设置REST服务的几件事:
以下工作代码:
@Configuration
@EnableWebSecurity
@ComponentScan("com.springapp.mvc")
@Order(1)
public class ApiWebConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private ApplicationAuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(apiEntryPoint())
.and()
.formLogin()
.failureHandler(failureHandler())
.successHandler(successHandler())
.and()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest()
.fullyAuthenticated();
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http
.requiresChannel()
.antMatchers("/api/**")
.requiresSecure();
http
.portMapper()
.http(8080)
.mapsTo(8443);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider)
.authenticationEventPublisher(authenticationEventPublisher())
.eraseCredentials(true);
}
AuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher(new ApiWebApplicationEventPublisher());
}
AuthenticationEntryPoint apiEntryPoint() {
return new ApiEntryPoint();
}
AuthenticationFailureHandler failureHandler() {
return new ApiAuthenticationFailureHandler();
}
AuthenticationSuccessHandler successHandler() {
return new ApiAuthenticationSuccessHandler();
}
static final class ApiWebApplicationEventPublisher implements org.springframework.context.ApplicationEventPublisher {
@Override
public void publishEvent(ApplicationEvent event) {
}
}
static final class ApiEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
static final class ApiAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
}
}
static final class ApiAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
}
}
}
控制器:
@Controller
@RequestMapping(value = "/api")
class APIController {
@Autowired
private MeetingsService meetingsService;
@RequestMapping(value="/meetings/{id}.json", method= RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public Object returnMeetingByIdOrEmpty(@PathVariable("id") final Long id) {
try {
final Meeting meeting = meetingsService.findById(id).get();
return meeting;
} catch (RuntimeException e) {
return JSONObject.NULL;
}
}
}
希望我帮助过任何人,
干杯