【问题标题】:Customize SpringSecurity OAuth 2 Error Output (unauthorized)自定义 Spring Security OAuth2 错误输出(未经授权)
【发布时间】:2013-02-13 04:19:11
【问题描述】:

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

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

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

设置拒绝访问页面是不行的。一方面,它需要定义一个我们没有的登录页面,因为这是一个纯服务器到服务器的通信。另一方面,这个属性据说自 Spring 3.0.. 或其他东西以来已被弃用。

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

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

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

谢谢!

编辑

对于我们当前的设置检查my other SO question here

【问题讨论】:

  • 我现在正在尝试做同样的事情。不知道怎么解决的,如果有解决方法,请分享。我发现了这个(下面的链接)论坛讨论,它似乎与使用 RestTemplate 的处理程序有关...forum.springsource.org/…
  • 我想我现在明白了,OAuth 服务器不会处理错误和重定向,这是客户端应用程序尝试进​​行身份验证的责任。我说的对吗?
  • 我现在不知道这是否适用于 OAuth 但不会完成这项工作?
  • 不,那行不通.. 试过了.. 必须定义一个登录页面等等,即使我不需要它,但它仍然会被忽略。我认为它不会产生实际的 403 响应

标签: java spring-security oauth-2.0


【解决方案1】:

我也必须删除 oauth 细节,我的解决方案是实现我自己的 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 上下文中引用它

     <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"/>

希望对你有帮助。

【讨论】:

  • 谢谢!所以就像我想的那样..会尽快尝试你的解决方案
  • 这仅在错误是 OAuth2 客户端错误时有效。但是如果错误是密码错误,我就无法让它工作......我疯狂地调试spring类并且无法做到。
猜你喜欢
  • 2019-08-09
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 2020-05-11
相关资源
最近更新 更多