Spring Oauth2 - 自定义异常处理程序

时间:2015-07-27 18:36:39

标签: java spring oauth spring-security

在Spring Security基于Oauth2的身份验证中,当客户端发送需要刷新的访问令牌时,DefaultTokenServices类会抛出InvalidTokenException(参见第235行):

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/DefaultTokenServices.java

发生这种情况时的输出类似于:

{"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"
}

我想改变这个输出,但我迷路了。其他一些答案建议设置自定义 exceptionRenderer ,但这也不起作用,我的自定义异常渲染器在这些情况下永远不会被调用。

还有一种称为异常翻译器的东西,但无论如何都没有调用它们。

我的春季配置的一部分:

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


<bean id="oauthAuthenticationEntryPoint"
      class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
      <property name="exceptionRenderer" ref="myExceptionRenderer" />
      <property name="exceptionTranslator" ref="listyOauthExceptionTranslator" />
</bean>

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

<bean id="myExceptionRenderer" class="com.example.exceptions.MyOauth2ExceptionRenderer" />

<bean id="myExceptionTranslator" class="com.example.exceptions.MyOauth2ExceptionTranslator" />

异常渲染器:

public class MyExceptionRenderer implements OAuth2ExceptionRenderer {

@Override
public void handleHttpEntityResponse(HttpEntity<?> responseEntity, ServletWebRequest webRequest) throws Exception {
    System.out.println("Thrown exception");
}

}

我还添加了一个自定义的异常映射器,它应该获得所有异常,但是因为我假设它的另一个servlet,在这种情况下这不起作用吗?

@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {

@Override 
public Response toResponse(Throwable ex) {
    System.out.println("MAPPING EXCEPTION");
    return Response.status(200).entity().build();
}
}

我可以捕获 AuthenticationException 的案例,但不能查看任何 InvalidTokenExceptions

对此有何帮助? Spring实际上在哪里捕获此InvalidTokenException以及如何设置它以便我可以提供自定义输出?

4 个答案:

答案 0 :(得分:5)

InvalidTokenException扩展ClientAuthenticationException。因此,您可以通过扩展ClientAuthenticationException并将其抛出而不是InvalidTokenException

来创建自己的例外
public class CustomException extends ClientAuthenticationException {

    public CustomException(String msg, Throwable t) {
        super(msg, t);
    }

    public CustomException(String msg) {
        super(msg);
    }
    @Override
    public String getOAuth2ErrorCode() {
        return "my_custom_exception";
    }
}

throw new CustomException("Invalid access token: " + accessTokenValue);

InvalidTokenException抛出的错误

 {"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"}

invalid_token由InvalidTokenException的getOAuth2ErrorCode()方法返回,Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9是您抛出异常时提供的消息。

如果你抛出

 throw new CustomException("This is my custom exception");

错误将显示为

{"error":"my_custom_exception","error_description":"This is my custom exception"}

my_custom_exception来自getOAuth2ErrorCode()的{​​{1}}。

答案 1 :(得分:3)

答案并没有真正提供自定义实现,自定义响应将是我可以访问默认响应的代码点,我可以发送POJO而不是它,例如,如果您想要更改error_descriptionerror_info或其他任何内容,或者您​​可能希望在响应中添加更多变量。解决方案确实存在,但我认为实施至少可以说是痛苦的,因为我从here复制它:

  

这个问题已经解决了。请遵循以下解决方法:   1将OAuth2Exception扩展到新类,例如CustomOAuth2Exception。在自定义类中,添加一些特定属性。   2自定义DefaultWebResponseExceptionTranslator并在AuthorizationServerConfiguration中注册自定义转换程序。   3个自定义的两个jackson序列化程序在OAuth2Exception中注释,并使用两个自定义序列化程序注释您的CustomOAuth2Exception。   4使用ObjectMapper覆盖带有自定义序列化程序的初始序列化程序。

答案 2 :(得分:0)

{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
{
"error": "invalid_token",
"error_description": "Invalid access token: 82b47091-c752-4832-b5dd-96a4da4df999"
}
{
"error": "access_denied",
"error_description": "not allowed access"
}

对于这些回复,请尝试我的答案 Spring Security Oauth - Custom format for OAuth2Exceptions

答案 3 :(得分:0)

覆盖

{"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"
}

您需要继承ResourceServerConfigurerAdapter 并覆盖public void configure(最终ResourceServerSecurityConfigurer配置)

示例代码

package com.org.security;

import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.stereotype.Component;


@Component
public class CustomWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator {

    /**
     * Modify OAuth2.0 Error Response
     * @param e
     * @return ResponseEntity<OAuth2Exception>
     * @throws Exception
     */

    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
        ResponseEntity responseEntity = super.translate(e);
        OAuth2Exception auth2Exception = (OAuth2Exception)responseEntity.getBody();
        if (auth2Exception != null) {
            auth2Exception.addAdditionalInformation("data", null);
            auth2Exception.addAdditionalInformation("message", auth2Exception.getMessage());
            auth2Exception.addAdditionalInformation("statusCode", String.valueOf(auth2Exception.getHttpErrorCode()));
        }
        return new ResponseEntity<OAuth2Exception>(auth2Exception, responseEntity.getHeaders(), responseEntity.getStatusCode());
    }
}





package com.org.security;

import com.org.exception.CustomAuthExceptionEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;


@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private ResourceServerTokenServices tokenServices;

    @Autowired
    private WebResponseExceptionTranslator oauth2ResponseExceptionTranslator;

    @Override
    public void configure(final ResourceServerSecurityConfigurer config) {
        OAuth2AccessDeniedHandler auth2AccessDeniedHandler = new OAuth2AccessDeniedHandler();
        auth2AccessDeniedHandler.setExceptionTranslator(oauth2ResponseExceptionTranslator);
        OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        authenticationEntryPoint.setExceptionTranslator(oauth2ResponseExceptionTranslator);
        config.tokenServices(tokenServices).accessDeniedHandler(auth2AccessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint);
    }

}