【问题标题】:Internationalization in Spring Oauth exception messagesSpring Oauth 异常消息中的国际化
【发布时间】:2017-07-13 15:55:16
【问题描述】:

是否可以本地化 Spring Oauth2 错误消息?尤其是 InvalidGrantException 和 UsernameNotFoundException 的错误消息。

【问题讨论】:

  • 我怀疑InvalidGrantException 的情况不是这样。 UsernameNotFoundException 是 Spring Security 核心的一部分,所以它可能有一些 i18n。这可能完全取决于您要将它们本地化的位置 - 如果它在日志文件中,您可能不走运。
  • @DaveSyer 我愿意接受建议。如果我可以在数据库级别将它们本地化,我愿意。
  • 不确定您所说的“数据库”是什么意思。谁将使用您的本地化数据?
  • @DaveSyer DB 作为本地化抽象的数据库。我的数据的消费者是最终用户。在这种情况下,我想确保在出现错误时提供本地化的翻译文本。
  • 用户通常不会看到安全异常消息。具体是什么场景?

标签: java spring spring-security spring-security-oauth2


【解决方案1】:

也许这太晚了,但我会把我的答案留在这里,让其他人感兴趣。

据我所知,Spring OAuth2 中没有内置的国际化功能(如果我错了,请纠正我)。但是,Spring 允许我们扩展默认实现以启动它。我猜有两种可能的方法:

1.后端

将服务器上的错误消息国际化并将其返回给 API。这需要区域设置解析(例如标头区域设置解析)

2。后端+前端

在您的响应中附加额外的错误代码,前端需要将它们映射到本地化消息中。

这个想法是实现一个自定义 TokenGranter 并将 AuthenticationException 转换为您自己的身份验证异常(例如 InvalidGrantException)。

下面的示例为不同类型的 invalid_grant 创建不同的错误代码(appoache #2):

    public class CustomTokenGranter extends AbstractTokenGranter {

        private static final String ERROR_CODE_KEY = "error_code";

        @Override
        protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
            try {
                ....
                authenticationManager.authenticate(...);
            } catch (AccountStatusException ase) {
                mapAndThrow(ase);
            } catch (BadCredentialsException e) {
                InvalidGrantException ige = new InvalidGrantException("Bad credentials");
                ige.addAdditionalInformation(ERROR_CODE_KEY, "01234");
                throw ige;
            }
        }


        private void mapAndThrow(AccountStatusException ase) {
            InvalidGrantException ige = new InvalidGrantException(ase.getMessage());
            if (ase instanceof DisabledException) {
                ige.addAdditionalInformation(ERROR_CODE_KEY, "01235");
            } else if (ase instanceof LockedException) {
                ige.addAdditionalInformation(ERROR_CODE_KEY, "01236");
            } else if (ase instanceof AccountExpiredException) {
                ige.addAdditionalInformation(ERROR_CODE_KEY, "01237");
            }
            // More goes here
            throw ige;
        }
    }

将自定义令牌授予者注册到您的授权服务器:

@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenGranter(new CustomTokenGranter (...));
    }
}

示例响应:

{
    "error": "invalid_grant",
    "error_description": "User is disabled",
    "error_code": "01235"
}

如果您想采用方法#1,您可以执行类似于方法#2 的操作,并通过从 RequestContextHolder 获取 servlet 请求来解析您的语言环境:

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) {
    HttpServletRequest sRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
    Locale locale = sRequest.getLocale(); ...
    // Resolve your error messages here from above obtained locale
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    • 2018-11-15
    • 1970-01-01
    相关资源
    最近更新 更多