顾乔芝士网

持续更新的前后端开发技术栈

Spring Cloud实战 | 第十篇: Bad client credentials异常自定义信息

Spring Cloud实战 | 第十篇: 授权服务器ljf-auth 实现Bad client credentials异常自定义信息返回

分析: 之前两种异常方式都可以通过全局异常处理器捕获,且@RestControllerAdvice只能捕获Controller的异常。 客户端认证的异常则是发生在过滤器filter上,此时还没进入DispatcherServlet请求处理流程,便无法通过全局异常处理器捕获。

1、添加CustomAuthenticationEntryPoint 设置异常响应数据格式

/**
* @Auther: lijinfeng
* @Date: 2021/12/22
* @Description 如果直接通过AuthenticationEntryPoint是无法自定义返回的信息,我们需要重写过滤器ClientCredentialsTokenEndpointFilter
*/
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {


    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        response.setStatus(HttpStatus.OK.value());
        Result r = Result.error(ResultEnum.ERROR_AuthenticationEntryPoint, "client_id或client_secret错误");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.getWriter().print(JSONUtil.toJsonStr(r));
        response.getWriter().flush();
    }
}

2、添加CustomClientCredentialsTokenEndpointFilter 达到替换AuthenticationEntryPoint的目的

**
* @Auther: lijinfeng
* @Date: 2021/12/22
* @Description 描述: 如果直接通过AuthenticationEntryPoint是无法自定义返回的信息,我们需要重写过滤器ClientCredentialsTokenEndpointFilter。
*/
public class CustomClientCredentialsTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter {


    private AuthorizationServerSecurityConfigurer configurer;
    private AuthenticationEntryPoint authenticationEntryPoint;


    public CustomClientCredentialsTokenEndpointFilter(AuthorizationServerSecurityConfigurer configurer) {
        this.configurer = configurer;
    }


    @Override
    public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
        // 把父类的干掉
        super.setAuthenticationEntryPoint(null);
        this.authenticationEntryPoint = authenticationEntryPoint;
    }


    @Override
    protected AuthenticationManager getAuthenticationManager() {
        return configurer.and().getSharedObject(AuthenticationManager.class);
    }


    @Override
    public void afterPropertiesSet() {
        setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                authenticationEntryPoint.commence(httpServletRequest, httpServletResponse, e);
            }
        });
        setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                // 无操作-仅允许过滤器链继续到令牌端点
            }
        });
    }


}

3、修改AuthorizationServerSecurityConfigurer,注入上面的修改

@Override
public void configure(AuthorizationServerSecurityConfigurer security) {

    CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security);
    endpointFilter.afterPropertiesSet();
    endpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint);

    security
            // 允许所有人请求令牌
            .tokenKeyAccess("permitAll()")
            // 已验证的客户端才能请求check_token端点
            .checkTokenAccess("isAuthenticated()")
            //实现Bad client credentials异常自定义信息返回 注意:security不需要在调用allowFormAuthenticationForClients方法
            .addTokenEndpointAuthenticationFilter(endpointFilter)
            // ~ 允许客户端表单验证
            //   只对 /oauth/token 端点有响应
            //   该设定会开启一个在 BasicAuthenticationFilter 前执行的过滤器, 名为 ClientCredentialsTokenEndpointFilter. 这个过滤器
            //   会尝试从请求参数中获取 client_id 和 client_secret 以完成认证
       //     .allowFormAuthenticationForClients()

      ;
}

4、请求报自定义异常



控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言