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

Posted

技术标签:

【中文标题】Spring Oauth2 - 自定义异常处理程序【英文标题】:Spring Oauth2 - custom exception handler 【发布时间】:2015-10-18 02:06:54 【问题描述】:

在基于 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 但这也不起作用,我的自定义异常渲染器在这些情况下永远不会被调用。

还有一种叫做异常翻译器的东西,但它们在任何情况下都没有被调用。

我的 Spring 配置的一部分:

<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,我该如何设置它以便提供自定义输出?

【问题讨论】:

您使用的是哪个版本的 Oauth2? 2.0.71.*? 4.0.5.RELEASE3.2.4.RELEASE2.0.3.RELEASE 1.0.2.RELEASE 【参考方案1】:

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()CustomException

【讨论】:

我不能使用自定义异常,因为它是 Spring Security Servlet 并且我的异常映射器永远不会被调用。我也发现了这个,但是我不知道如何通过xml配置这个? @breakline 你不能使用自定义异常是什么意思?在您的 DefaultTokenServices 中抛出此自定义异常。 @breakline 您发布的问题谈到了更改OAuth2EntryPoint。如果你只需要改变异常,你可以这样做。 如果覆盖 DefaultTokenServices.loadAuthentication,则需要抛出 AuthenticationException 或 InvalidTokenException。如果你覆盖第一个,你会得到一个 500 服务器错误,我假设这是 servlet 中的默认处理程序。如果您覆盖后者,则不会发生任何事情,因为它仍然是 RuntimeException 并且 Spring Security Servlet 会处理它 @Karthik 如何在 spring-security xml 文件中配置这个 CustomException 类?请告诉我【参考方案2】:

用于覆盖

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

你需要继承 ResourceServerConfigurerAdapter 并覆盖 public void configure(final ResourceServerSecurityConfigurer config)

示例代码

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);
    


【讨论】:

如何删除现有的error_descriptionerror【参考方案3】:

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

这个问题已经解决了。请遵循以下解决方法:

    OAuth2Exception 扩展到一个新的类,例如 自定义 OAuth2 异常。在自定义类中,添加一些特定的 属性。 自定义DefaultWebResponseExceptionTranslator和 在AuthorizationServerConfiguration注册自定义翻译器。 自定义两个在OAuth2Exception 中注释的杰克逊序列化程序和 用两个自定义注释你的CustomOAuth2Exception 序列化器。 使用ObjectMapper 覆盖初始序列化程序 自定义序列化程序。

【讨论】:

【参考方案4】:

这是我对自定义 AuthorizationServer 和 ResourceServer 异常的解决方案。也许会有所帮助。

Spring Security Oauth - Custom format for OAuth2Exceptions

【讨论】:

以上是关于Spring Oauth2 - 自定义异常处理程序的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud:Security OAuth2 自定义异常响应

Spring Cloud:Security OAuth2 自定义异常响应

使用 Spring Security 自定义客户端身份验证的 OAuth2 错误响应

Spring Boot 异常自定义处理 - 意外的 HTTP 状态

Spring OAuth2 自定义身份验证管理器 ClassCastException

缺少资源 bean:Spring Boot webflux 自定义全局异常处理程序