Java 自定义SpringSecurity OAuth 2错误输出(未经授权)

Java 自定义SpringSecurity OAuth 2错误输出(未经授权),java,spring-security,oauth-2.0,Java,Spring Security,Oauth 2.0,我们使用SpringSecurityOAuth2保护REST服务(用于服务器到服务器的通信,不涉及用户)。但是,当用户尝试在浏览器中访问受保护的资源时,它将显示: <oauth> <error_description> An Authentication object was not found in the SecurityContext </error_description> <error>unauth

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

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

在SecurityContext中找不到身份验证对象
未经授权
我们希望这是一个我们自己选择的自定义页面。有办法吗

设置拒绝访问页面不起作用。首先,它需要定义一个我们没有的登录页面,因为这是一个纯服务器到服务器的通信。另一方面,自Spring3.0以来,该属性被认为是不推荐使用的。。或者别的什么

无论如何。。调试了OAuth错误处理。发现我在错误页面上看到的信息似乎丰富了我的反应。显然根本没有进行页面渲染,所以看起来没有要替换的错误页面

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

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

谢谢

编辑


对于当前的设置检查,我也必须删除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);
    }
}
package org.some.nice.code;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入org.apache.commons.logging.Log;
导入org.apache.commons.logging.LogFactory;
导入org.springframework.http.HttpEntity;
导入org.springframework.http.HttpHeaders;
导入org.springframework.http.HttpInputMessage;
导入org.springframework.http.HttpOutputMessage;
导入org.springframework.http.ResponseEntity;
导入org.springframework.http.server.ServerHttpResponse;
导入org.springframework.http.server.ServletServerHttpRequest;
导入org.springframework.http.server.ServletServerHttpResponse;
导入org.springframework.security.oauth2.provider.error.OAuth2ExceptionRenderer;
导入org.springframework.web.context.request.NativeWebRequest;
导入org.springframework.web.context.request.ServletWebRequest;
公共类HeaderOnlyAuth2ExceptionRenderer实现OAuth2ExceptionRenderer
{
专用最终日志记录器=日志工厂
.getLog(myAuth2ExceptionRenderer.class);
公共无效handleHttpEntityResponse(HttpEntity responseEntity,
ServletWebRequest(webRequest)引发异常
{
if(responseEntity==null)
{
返回;
}
HttpInputMessage inputMessage=createHttpInputMessage(webRequest);
HttpOutputMessage outputMessage=createHttpOutputMessage(webRequest);
info(“仅过滤标题…”);
if(responseEntity)responseEntity的实例
&&服务器的outputMessage实例(HttpResponse)
{
((ServerHttpResponse)输出消息)
.setStatusCode(((ResponseEntity)ResponseEntity)
.getStatusCode());
}
HttpHeaders entityHeaders=responseEntity.getHeaders();
如果(!entityHeaders.isEmpty())
{
outputMessage.getHeaders().putAll(entityHeaders);
}
}
私有HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest)
抛出异常
{
HttpServletRequest servletRequest=webRequest
.getNativeRequest(HttpServletRequest.class);
返回新的ServletServerHttpRequest(servletRequest);
}
私有HttpOutputMessage createHttpOutputMessage(
NativeWebRequest(webRequest)引发异常
{
HttpServletResponse servletResponse=(HttpServletResponse)webRequest
.getNativeResponse();
返回新的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"/>


希望能有帮助。

我现在也在努力做同样的事情。还不知道如何,如果你有解决方案,请分享。我发现了这个(下面的链接)论坛讨论,它似乎与使用RestTemplate的处理程序有关。。。我想我现在明白了,OAuth服务器不会处理错误和重定向,这是试图进行身份验证的客户端应用程序的责任。我说的对吗?我现在不知道这是否能与OAuth一起工作,但不会完成这项工作?不,那不行。。试过了。。必须定义一个登录页面和更多,即使我不需要它,但它仍然会被忽略。我认为它不会产生实际的403个响应!正如我所想。。将尝试您的解决方案,因为这仅在错误为OAuth2客户端错误时有效。但是如果错误是密码错误,我就无法让它工作。。。我疯狂地调试春季课程,但没能完成。