资源服务器异常处理

v4.6 版本及其以上版本

在 4.6 版本中 pigx 将默认的 AuthenticationException 处理器修改成如下

@RequiredArgsConstructor
public class ResourceAuthExceptionEntryPoint implements AuthenticationEntryPoint {

	private final ObjectMapper objectMapper;

	private final MessageSource messageSource;

	@Override
	@SneakyThrows
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) {
		response.setCharacterEncoding(CommonConstants.UTF8);
		response.setContentType(ContentType.JSON.getValue());
		R<String> result = new R<>();
		result.setCode(CommonConstants.FAIL);
		response.setStatus(HttpStatus.UNAUTHORIZED.value());
		if (authException != null) {
			result.setMsg("error");
			result.setData(authException.getMessage());
		}

		// 针对令牌过期返回特殊的 424
		if (authException instanceof InvalidBearerTokenException
				|| authException instanceof InsufficientAuthenticationException) {
			response.setStatus(HttpStatus.FAILED_DEPENDENCY.value());
			result.setMsg(this.messageSource.getMessage("OAuth2ResourceOwnerBaseAuthenticationProvider.tokenExpired",
					null, LocaleContextHolder.getLocale()));
		}
		PrintWriter printWriter = response.getWriter();
		printWriter.append(objectMapper.writeValueAsString(result));
	}

}

会处理所有 AuthenticationException 的子类进行错误返回,可根据自己对不同业务单独进行判断处理

低版本修改

低版本修改示意

原理篇

目标

如上图, pigx 在默认登录失败的情况下,只会返回给前端 用户名或密码不正确 的业务提示。 在实际的业务过程中,需要基于项目需要给客户端更多的明确信息提示。

代码扩展

  • 如果你已经看了 登录 token 生成 章节的文档,那么肯定就会知道 spring security 最终是通过的 UserDetailsService.loadUserByUsername 来加载项目的用户体系至 spring security oauth 完成认证授权。
UserDetailsService加载用户体系
  • 如上所述,系统目前只抛出 用户名或密码不正确
异常抛出示意
  • 此处可以根据 feign 调用 upms 查询结果进行更细化处理,扔出新的异常 PigxAuth2Exception
private UserDetails getUserDetails(R<UserInfo> result) {
    //此处根据feign 查询结果进行个性化判断 扔出PigxAuth2Exception
    if ("1".equals(result.getData().getSysUser().getLockFlag())) {
        throw new PigxAuth2Exception("账号已被锁定");
    }
}

原理解析

  • 此处扔出的异常都会被 PigxWebResponseExceptionTranslator.translate 集中格式化处理

最终调用 PigxAuth2ExceptionSerializer 序列化规则输出给客户端

public class PigxAuth2ExceptionSerializer extends StdSerializer<PigxAuth2Exception> {

	public PigxAuth2ExceptionSerializer() {
		super(PigxAuth2Exception.class);
	}

	@Override
	@SneakyThrows
	public void serialize(PigxAuth2Exception value, JsonGenerator gen, SerializerProvider provider) {
		gen.writeStartObject();
		gen.writeObjectField("code", CommonConstants.FAIL);
		gen.writeStringField("msg", value.getMessage());
		gen.writeStringField("data", value.getErrorCode());
		gen.writeEndObject();
	}

}