小编典典

当用户登录时,Spring保存语言环境并更改语言环境

java

我有一个Spring应用程序,希望用户能够更改首选语言环境。当前,用户可以更改当前会话的语言环境,但是我希望能够保存users选项,以便每当他们登录时,使用已保存的语言环境(如果存在)。我有一个mysql数据库,用于存储用户区域设置首选项。我创建了一个自定义AuthenticationSuccessHandler,以处理将语言环境更改为已保存的语言环境的操作,该方法适用于已将语言环境保存到数据库的用户。但是,我不知道该怎么做是在更改选项时保存语言环境。代码如下:

   /**
     * Creates and gets the LocaleResolver
     * @return LocaleResolver
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver slr = new SessionLocaleResolver();
        slr.setDefaultLocale(Locale.getDefault());
        logger.debug("Setting locale to: " + Locale.getDefault());
        return slr;
    }

    /**
     * Creates and gets the LocaleChangeInterceptor
     * @return LocaleChangeInterceptor
     */
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang");
        logger.debug("localeChangeInterceptor called "  + Locale.getDefault());
        return lci;
    }

SecurityConfig类:

@Configuration("SecurityConfig")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
class SecurityConfig extends WebSecurityConfigurerAdapter 
{

    @Autowired
    @Qualifier("CustomAuthenticationSuccessHandler")
    private CustomAuthenticationSuccessHandler authenticationSuccessHandler;


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding(StandardCharsets.UTF_8.name());
        filter.setForceEncoding(true);
        http.addFilterBefore(filter,CsrfFilter.class);
        // configure authentication providers
        http.authenticationProvider( customAuthenticationProvider() );
        http.authenticationProvider( authenticationProvider() );

        http.authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/?lang=**").permitAll()
            .antMatchers("/login**").permitAll()
            .antMatchers("/about**").permitAll()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/css/**").permitAll()
            .antMatchers("/js/**").permitAll()
            .antMatchers("/img/**").permitAll()
            .antMatchers("/fonts/**").permitAll()
            .antMatchers("/errors/**").permitAll()
            .antMatchers("/error/**").permitAll()
            .antMatchers("/webjars/**").permitAll()
            .antMatchers("/static/**").permitAll()
            .antMatchers("/information/**").permitAll() 
            .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
            .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/home")
                .failureUrl("/login?failedlogin=true")
                .usernameParameter("username").passwordParameter("password")
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .permitAll()

            .and()
                .logout()
                .deleteCookies("JSESSIONID")
                .addLogoutHandler(getCustomLogoutSuccessHandler())
                .invalidateHttpSession(true) 
                .permitAll()

            .and()
                .csrf().disable()
                .exceptionHandling()
            .and()
                    .rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository)
                    .tokenValiditySeconds(86400)
                ;
    }

    ....
}

AuthenticationSuccessHandler类

@Component("CustomAuthenticationSuccessHandler")
public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    /** Logger */
    private static final Logger logger = LogManager.getLogger(CustomAuthenticationSuccessHandler.class);

    @Autowired
    private LocaleResolver localeResolver;

    @Autowired
    @Qualifier("UserService")
    private UserService userService;


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        logger.debug("CustomAuthenticationSuccessHandler.onAuthenticationSuccess called");
        setLocale(authentication, request, response);
        super.onAuthenticationSuccess(request, response, authentication);
    }

    protected void setLocale(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
        logger.debug("CustomAuthenticationSuccessHandler.setLocale called");
        if (authentication != null &&authentication.getPrincipal() != null) {
            String username = (String) authentication.getPrincipal();

            if (username != null) {

                String localeOption = userService.getUsersPreferedLocaleOption(username);
                logger.debug("localeOption " + localeOption);
                if (localeOption != null && !localeOption.isEmpty()) {
                    Locale userLocale = Locale.forLanguageTag(localeOption);
                    localeResolver.setLocale(request, response, userLocale);

                }

            }
        }
    }

}

显示语言更改选项的html页面的一部分:

<form id="change-language-form" name="change-language-form" class="change-language-form ng-pristine ng-valid" method="POST">
            <div class="row">
                <div class="text-right col-sm-offset-8 col-sm-4">
                    <select id="language-selector" name="language-selector" class="language-selector">
                        <option value="">Language </option>
                        <option value="?lang=en_GB">English </option>
                        <option value="?lang=zh">中文 </option>
                        <option value="?lang=de_DE">Deutsch </option>
                        <option value="?lang=es_ES">Español </option>
                        <option value="?lang=fr_FR">Français </option>
                    </select>
                </div>
            </div>
            <div class="row">
               <div class="spacer-sml"></div>
            </div>
        </form>

更改语言选项的Javascript:

$('#language-selector').change(function() {

    var languageSelectedUrl = $(this).find("option:selected").val();      
    if (languageSelectedUrl) {
        window.location = languageSelectedUrl;
    }
});

阅读 162

收藏
2020-11-16

共1个答案

小编典典

您可以实现LocaleResolver接口以将用户Locale绑定到数据库。下面是示例实现
ApplicationLocaleResolver.java”

import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import net.app.locale.service.UserService;

@Configuration
public class ApplicationLocaleResolver extends SessionLocaleResolver {
    @Autowired
    UserService userService;

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        String userName = securityContext.getAuthentication().getName();
        String localeOption = userService.getUsersPreferedLocaleOption(userName);
        Locale userLocale = Locale.forLanguageTag(localeOption);
        return userLocale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        super.setLocale(request, response, locale);

        SecurityContext securityContext = SecurityContextHolder.getContext();
        String userName = securityContext.getAuthentication().getName();
        userService.saveUsersPreferedLocaleOption(userName, locale);
    }
}

我假设您的userService具有将用户保存到db本地的方法。我希望userService.saveUsersPreferedLocaleOption(userName, locale);您可以更改它。

然后,您可以如下替换localeResolver bean定义。

@Bean(name = "localeResolver")
public LocaleResolver localeResolver() {
    return new ApplicationLocaleResolver();
}
2020-11-16