自定义 SpringSecurity OAuth 2 错误输出(未授权) [英] Customize SpringSecurity OAuth 2 Error Output (unauthorized)

查看:63
本文介绍了自定义 SpringSecurity OAuth 2 错误输出(未授权)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用 Spring Security OAuth2 保护我们的 REST 服务(用于服务器到服务器通信,不涉及用户).但是,当您尝试在浏览器中访问受保护的资源时,它会显示:

We secure our REST services (for server to server communication, no user involved) with Spring Security OAuth2. However when one tries to access a protected resource in a browser, it will show:

<oauth>
    <error_description>
        An Authentication object was not found in the SecurityContext
    </error_description>
    <error>unauthorized</error>
</oauth>

我们希望这是我们自己选择的自定义页面.有办法吗?

We want this to be a custom page of our own choosing. Is there a way?

设置拒绝访问页面不起作用.一方面,它需要定义一个登录页面,我们没有,因为这是一个纯粹的服务器到服务器通信.另一方面,这个属性从 Spring 3.0 开始就被弃用了.

Setting the access-denied-page won't do. For one it requires the definition of a login page which we don't have as this is a pure server to server communication. For another this attribute is supposedly deprecated since Spring 3.0.. or something.

无论如何.. 调试我进入 OAuth 错误处理的方式.并发现响应似乎以某种方式丰富了我在错误页面上看到的信息.显然根本没有进行页面渲染,所以看起来没有要替换的错误页面......?!

Anyway.. Debugged my way into the OAuth Error Handling. And found that the response seems to somehow get enriched with the information I see on the error page. Apparently no page rendering at all is done so it looks like there is no error page to replace..?!

至少我们想隐藏我们使用 OAuth 的事实,如果我们不能拥有真实"页面,则只显示一个基本的拒绝"文本..所以也许我必须扩展 spring 安全处理程序或添加自定义过滤器来修改响应?!

At least we want to hide the fact that we use OAuth and just display a basic "Denied" text if we can't have a "real" page.. So maybe I'll have to extend the spring security handler or add a custom filter to modify the response?!

也许会重定向到我们的错误页面?

Maybe a redirect to our error page?

谢谢!

编辑

对于我们当前的设置,请检查 我的其他所以问题在这里

For our current setup check my other SO question here

推荐答案

我也不得不删除 oauth 细节,我的解决方案是实现我自己的 OAuth2ExceptionRenderer

I had to remove the oauth detail too and my solution was to implement my own OAuth2ExceptionRenderer

package org.some.nice.code;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.oauth2.provider.error.OAuth2ExceptionRenderer;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;

public class HeaderOnlyOAuth2ExceptionRenderer implements OAuth2ExceptionRenderer
{
    private final Log logger = LogFactory
            .getLog(MyOAuth2ExceptionRenderer.class);

    public void handleHttpEntityResponse(HttpEntity<?> responseEntity,
            ServletWebRequest webRequest) throws Exception
    {
        if (responseEntity == null)
        {
            return;
        }
        HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
        HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
        logger.info("filtering headers only...");
        if (responseEntity instanceof ResponseEntity
                && outputMessage instanceof ServerHttpResponse)
        {
            ((ServerHttpResponse) outputMessage)
                    .setStatusCode(((ResponseEntity<?>) responseEntity)
                            .getStatusCode());
        }
        HttpHeaders entityHeaders = responseEntity.getHeaders();
        if (!entityHeaders.isEmpty())
        {
            outputMessage.getHeaders().putAll(entityHeaders);
        }
    }

    private HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest)
            throws Exception
    {
        HttpServletRequest servletRequest = webRequest
                .getNativeRequest(HttpServletRequest.class);
        return new ServletServerHttpRequest(servletRequest);
    }

    private HttpOutputMessage createHttpOutputMessage(
            NativeWebRequest webRequest) throws Exception
    {
        HttpServletResponse servletResponse = (HttpServletResponse) webRequest
                .getNativeResponse();
        return new ServletServerHttpResponse(servletResponse);
    }
}

然后你必须在你的 spring 上下文中引用它

Then you will have to reference it within your spring context

     <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="theRealm" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
    </bean>

    <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
        <property name="realmName" value="theRealm/client" />
        <property name="typeName" value="Basic" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
    </bean>



    <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>


    <bean id="headerOnlyExceptionRender" class="org.some.nice.code.HeaderOnlyOAuth2ExceptionRenderer"/>

希望有帮助.

这篇关于自定义 SpringSecurity OAuth 2 错误输出(未授权)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆