如何强制Spring Security OAuth 2使用JSON而不是XML?

时间:2015-11-26 02:46:11

标签: java spring spring-mvc spring-security spring-security-oauth2

我已经创建了Spring MVC应用程序并设置了Spring Security OAuth 2。 从我的浏览器调用方法时,我得到了XML:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

浏览器发送以下标题:

pulp

当我设置json接受标头时,我得到了JSON。我需要强制我的授权服务器总是发送JSON。没有找到任何解决方案。感谢。

4 个答案:

答案 0 :(得分:6)

对于Spring Security,使用DefaultOAuth2ExceptionRenderer

呈现OAuth异常

它会将收到的Accept HTTP标头与提供的MessageConverters进行匹配。在您的情况下,Spring Boot似乎已自动分配XML和JSON MessageConverters。此行为已得到确认,基于Accept标头,您将收到以适当的Content-Type

呈现的异常

没有Accept标头 DefaultOAuth2ExceptionRenderer 默认为 Accept:* ,第一个MessageConverter通常响应是XML。

如果您的应用中不需要XML,您需要了解它为何得到支持(很可能您在类路径中有一个FasterXML Jackson)。

如果你想支持这两种方法,但想要使用JSON默认值,则需要编写自己的 OAuth2ExceptionRendrer 的impl,并确保以JSON格式呈现异常。更好的方法是将你的impl挂钩到 ContentNegotationManager 并将MediaType解析权委托给它。

有关 ContentNegotationManager 的详细信息,请查看以下链接:

https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

答案 1 :(得分:2)

_设置为标题属性

答案 2 :(得分:0)

迫使OAuth2变得非常容易,你只需先自己弄明白:

@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;

@Autowired
private AccessDeniedHandler accessDeniedHandler;

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .anyRequest()
            .access("#oauth2.hasScope('read')")
        .and()
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint)
            .accessDeniedHandler(accessDeniedHandler);
}

然后,您需要创建authenticationEntryPoint和accessDeniedHandler @Bean

@Bean
public AccessDeniedHandler accessDeniedHandler() {
    return new AccessDeniedHandler () {
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
            response.getWriter().append("\"FORBIDDEN\"");
            response.setStatus(HttpStatus.FORBIDDEN.value());
        }
    };

}

@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
    return new AuthenticationEntryPoint() {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
            response.getWriter().append("\"UNAUTHORIZED\"");
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        }
    };
}

您可以随心所欲地转换为JSON,我会向您推荐杰克逊。

答案 3 :(得分:0)

要扩展BigDong的答案,您不需要创建自己的入口点和异常处理程序类,只需替换呈现器并设置要使用的消息转换器的类型即可。例如,在我的Oauth2Config中,我执行以下操作:

    httpSecurity.authorizeRequests()
       .requestMatchers(getAuthorizedRequestMatcher())
       .authenticated()
       ...
       .and()
       .exceptionHandling().accessDeniedHandler(buildAccessDeniedHandler(configureExceptionRenderer()))
       .and()
       .exceptionHandling().authenticationEntryPoint(buildAuthenticationEntryPoint(configureExceptionRenderer()));

使用所需的消息转换器在创建渲染的位置:

    protected OAuth2ExceptionRenderer configureExceptionRenderer() {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();

        messageConverters.add(new MappingJackson2HttpMessageConverter(Jackson2ObjectMapperBuilder.json().applicationContext(this.applicationContext).build()));

        messageConverters.add(new ByteArrayHttpMessageConverter());
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
        stringConverter.setWriteAcceptCharset(false);
        messageConverters.add(stringConverter);
        ... add more if you want ...
        DefaultOAuth2ExceptionRenderer renderer = new DefaultOAuth2ExceptionRenderer();
        renderer.setMessageConverters(messageConverters);
        return renderer;
    }

最后实例化入口点和错误处理程序并设置渲染器:

    protected AuthenticationEntryPoint buildAuthenticationEntryPoint(OAuth2ExceptionRenderer renderer) {
        OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
        entryPoint.setExceptionRenderer(renderer);

        return entryPoint;
    }

    protected AccessDeniedHandler buildAccessDeniedHandler(OAuth2ExceptionRenderer renderer) {
        OAuth2AccessDeniedHandler handler = new OAuth2AccessDeniedHandler();
        handler.setExceptionRenderer(renderer);

        return handler;
    }