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

Java Spring Oauth2-自定义异常处理程序,java,spring,oauth,spring-security,Java,Spring,Oauth,Spring Security,在基于Spring Security Oauth2的身份验证中,当客户端发送需要刷新的访问令牌时,DefaultTokenServices类抛出InvalidTokenException(参见第235行): 发生这种情况时的输出类似于: {"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9" } 我想更改此输出,但我迷路了。其他一些答案建

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

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

{"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"
}
我想更改此输出,但我迷路了。其他一些答案建议设置一个自定义的异常渲染器,但这也不起作用,在这些情况下,我的自定义异常渲染器从未被调用

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

我的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");
}
公共类MyExceptionRenderer实现OAuth2ExceptionRenderer{
@凌驾
public void handleHttpEntityResponse(HttpEntity responseEntity,ServletWebRequest webRequest)引发异常{
System.out.println(“抛出异常”);
}
}

我还添加了一个定制的异常映射器,它应该可以获取所有的异常,但是因为我假设它是另一个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();
}
}
@Provider
公共类GenericeExceptionMapper实现ExceptionMapper{
@凌驾
公众对响应的响应(可丢弃的ex){
System.out.println(“映射异常”);
返回Response.status(200.entity().build();
}
}
我可以捕捉到AuthenticationException的情况,但不能捕捉到任何InvalidTokenException


有什么帮助吗?Spring在何处捕获此InvalidTokenException?如何设置它以提供自定义输出?

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";
    }
}

在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
来自
CustomException
getOAuth2ErrorCode()

答案并不是真正提供自定义实现,自定义响应将是代码中的一个点,我可以访问默认响应,我可以发送POJO而不是它,例如,如果您希望将
错误描述
更改为
错误信息
或其他任何内容,或者您可能希望向响应中添加更多变量。解决方案确实存在,但我认为实施起来很痛苦,至少可以这么说,因为我从以下方面复制了它:

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

  • OAuth2Exception
    扩展到一个新类,例如 CustomOAuth2Exception。在自定义类中,添加一些特定的 财产
  • 自定义
    DefaultWebResponseExceptionTranslator
    和 在
    AuthorizationServerConfiguration
    中注册自定义转换器
  • OAuth2Exception
    和中注释的自定义两个jackson序列化程序 用两个自定义项注释您的
    CustomOAuth2Exception
    序列化程序
  • 使用
    ObjectMapper
    用 自定义序列化程序

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

    用于覆盖

    {"error":"invalid_token","error_description":"Invalid access token: a0cb5ab9-7281-46bd-a9a2-796a04a906c9"
    }
    
    您需要继承ResourceServerConfigurerAdapter 并覆盖公共void配置(最终ResourceServerSecurityConfigure配置)

    示例代码

    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);
        }
    
    }
    
    package com.org.security;
    导入org.springframework.http.ResponseEntity;
    导入org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
    导入org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
    导入org.springframework.stereotype.Component;
    @组成部分
    公共类CustomWebResponseExceptionTranslator扩展了DefaultWebResponseExceptionTranslator{
    /**
    *修改OAuth2.0错误响应
    *@param e
    *@返回响应性
    *@抛出异常
    */
    @凌驾
    公共响应性翻译(异常e)引发异常{
    ResponseEntity ResponseEntity=super.translate(e);
    OAuth2Exception auth2Exception=(OAuth2Exception)responseEntity.getBody();
    if(auth2Exception!=null){
    auth2Exception.addAdditionalInformation(“数据”,null);
    auth2Exception.addAdditionalInformation(“message”,auth2Exception.getMessage());
    auth2Exception.addAdditionalInformation(“statusCode”,String.valueOf(auth2Exception.getHttpErrorCode());
    }
    返回新的ResponseEntity(auth2Exception,ResponseEntity.getHeaders(),ResponseEntity.getStatusCode());
    }
    }
    包com.org.security;
    导入com.org.exception.CustomAuthExceptionEntryPoint;
    导入org.springframework.beans.factory.annotation.Autowired;
    导入org.springframework.context.annotation.Configuration;
    导入org.springframework.security.config.annotation.web.builders.HttpSecurity;
    导入org.springframework.security.config.http.SessionCreationPolicy;
    导入org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    导入org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
    导入org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigure;
    导入org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
    导入org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
    导入org.springframework.security.oauth2.provider.error.WebResponseExceptionTran
    
    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);
        }
    
    }