Parse Accept-Language header in Java

后端 未结 7 711
孤城傲影
孤城傲影 2020-12-15 02:54

The accept-language header in request is usually a long complex string -

Eg.

Accept-Language : en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2


        
相关标签:
7条回答
  • 2020-12-15 03:45

    The above solutions lack some kind of validation. Using ServletRequest.getLocale() returns the server locale if the user does not provides a valid one.

    Our websites lately received spam requests with various Accept-Language heades like:

    1. secret.google.com
    2. o-o-8-o-o.com search shell is much better than google!
    3. Google officially recommends o-o-8-o-o.com search shell!
    4. Vitaly rules google ☆*:。゜゚・*ヽ(^ᴗ^)ノ*・゜゚。:*☆ ¯\_(ツ)_/¯(ಠ益ಠ)(ಥ‿ಥ)(ʘ‿ʘ)ლ(ಠ_ಠლ)( ͡° ͜ʖ ͡°)ヽ(゚Д゚)ノʕ•̫͡•ʔᶘ ᵒᴥᵒᶅ(=^ ^=)oO

    This implementation can optional check against a supported list of valid Locale. Without this check a simple request with "test" or (2, 3, 4) still bypass the syntax-only validation of LanguageRange.parse(String).

    It optional allows empty and null values to allow search engine crawler.

    Servlet Filter

    final String headerAcceptLanguage = request.getHeader("Accept-Language");
    
    // check valid
    if (!HttpHeaderUtils.isHeaderAcceptLanguageValid(headerAcceptLanguage, true, Locale.getAvailableLocales()))
        return;
    

    Utility

    /**
     * Checks if the given accept-language request header can be parsed.<br>
     * <br>
     * Optional the parsed LanguageRange's can be checked against the provided
     * <code>locales</code> so that at least one locale must match.
     *
     * @see LanguageRange#parse(String)
     *
     * @param acceptLanguage
     * @param isBlankValid Set to <code>true</code> if blank values are also
     *            valid
     * @param locales Optional collection of valid Locale to validate any
     *            against.
     *
     * @return <code>true</code> if it can be parsed
     */
    public static boolean isHeaderAcceptLanguageValid(final String acceptLanguage, final boolean isBlankValid,
        final Locale[] locales)
    {
        // allow null or empty
        if (StringUtils.isBlank(acceptLanguage))
            return isBlankValid;
    
        try
        {
            // check syntax
            final List<LanguageRange> languageRanges = Locale.LanguageRange.parse(acceptLanguage);
    
            // wrong syntax
            if (languageRanges.isEmpty())
                return false;
    
            // no valid locale's to check against
            if (ArrayUtils.isEmpty(locales))
                return true;
    
            // check if any valid locale exists
            for (final LanguageRange languageRange : languageRanges)
            {
                final Locale locale = Locale.forLanguageTag(languageRange.getRange());
    
                // validate available locale
                if (ArrayUtils.contains(locales, locale))
                    return true;
            }
    
            return false;
        }
        catch (final Exception e)
        {
            return false;
        }
    }
    
    0 讨论(0)
提交回复
热议问题