访问Spring Security配置中的messages.properties

时间:2016-03-21 01:04:21

标签: spring-mvc spring-security

我最近切换到Spring Security来处理我的Web应用程序的登录,注销和基于角色的访问。我使用flash消息来获取信息和错误消息,并希望在成功登录和注销后显示这样的消息。

在JSP文件中,使用以下代码显示这些消息:

<c:if test = "${not empty flashmessage_error}" >
  <div class="alert alert-danger"><c:out value="${flashmessage_error}" />
  </div>
</c:if>

<c:if test="${not empty flashmessage_info}" >
  <div class="alert alert-info"><c:out value="${flashmessage_info}" />
  </div>
</c:if>

要在成功登录后显示flash消息,我定义了一个自定义LoginSuccessHandler ,它将消息放入FlashMap并将重定向页面设置为主页:

public class FlashMessageAuthSuccessHandler extends
    SavedRequestAwareAuthenticationSuccessHandler {

private String flashMessage = "Logged in!";

public void setFlashMessage(String flashMessage) {
      this.flashMessage = flashMessage;
}

@Override
public void onAuthenticationSuccess(HttpServletRequest request,
        HttpServletResponse response, Authentication authentication)
        throws ServletException, IOException {

    FlashMapManager flashMapManager = new SessionFlashMapManager();

    FlashMap fm = new FlashMap();
    fm.put(KeyConstants.FLASH_INFO_KEY, flashMessage);

    flashMapManager.saveOutputFlashMap(fm, request, response);

    setDefaultTargetUrl("/");

    super.onAuthenticationSuccess(request, response, authentication);
}
}

我的 SecurityConfig 类如下所示:

@Configuration
@EnableWebSecurity(debug = false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Autowired
private MessageSource messageSource;


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

    auth.authenticationProvider(daoAuthenticationProvider());

}

/*
 * HttpSecurity allows configuring web based security for specific HTTP requests
 * By default it will be applies to all request, but can be restricted
 * using requestMatcher
 * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
 */

@Override
protected void configure(HttpSecurity http) throws Exception {
    //super.configure(http);

    http
        .authorizeRequests()
            .antMatchers("/", "/css/**", "/js/**", "/images/**", "/about", "/error").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .usernameParameter("j_username")
            .passwordParameter("j_password")
            .loginPage("/login")
            .loginProcessingUrl("/ssprocesslogin") //post request
//          .defaultSuccessUrl("/") //cannot possibly used in combination with successHandler?
            .successHandler(loginSuccesHandler())
            .failureUrl("/login?" + KeyConstants.FLASH_ERROR_KEY + "=Verkeerde login message aanpassen") //default is /login?error
            .permitAll()
            .and()
        .rememberMe()
            .tokenValiditySeconds(2592000)  //one month
            .rememberMeParameter("j_rememberme")
            .key("wIllekEUrigeSleutteL")
            .userDetailsService(userDetailsService)
        .and()
        .logout()
            .logoutUrl("/logout") //default is /logout
//          .logoutSuccessUrl("/") //default is /login?logout
            .logoutSuccessHandler(new FlashMessageLogoutSuccessHandler())
            .invalidateHttpSession(true) //true is the default
            ; 
}

@Bean
public FlashMessageAuthSuccessHandler loginSuccesHandler() {
    FlashMessageAuthSuccessHandler handler = new FlashMessageAuthSuccessHandler();

    //THIS DOES NOT WORK!!!!!
    String loginSuccessMessage = messageSource.getMessage("flashmessage.loginsuccesful", null, "not found", null);

    handler.setFlashMessage(loginSuccessMessage);
    return handler;
}

@Bean
public AuthenticationProvider daoAuthenticationProvider() {
    DaoAuthenticationProvider dap = new DaoAuthenticationProvider();
    dap.setUserDetailsService(userDetailsService);
    dap.setPasswordEncoder(passwordEncoder());

    return dap;
}

@Bean
public ShaPasswordEncoder passwordEncoder() {
    return new ShaPasswordEncoder(256);
}
}

但是没有显示来自messages.properties文件的正确消息。相反,字符串&#34;未找到&#34;登录后显示为flash消息。 在下面的行中,我尝试使用注入的MessageSource通过消息键查找消息,但显然找不到它并显示回退消息:

String loginSuccessMessage = messageSource.getMessage("flashmessage.loginsuccesful", null, "not found", null);

messageSource bean在MvcConfig文件中定义,如下所示,用于在JSP文件中显示消息时工作正常,但似乎无法在Spring Security配置文件中自动装配以获取所需的flash消息。

@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages");
    return messageSource;
}

我有什么想法可以做到这一点?

4 个答案:

答案 0 :(得分:0)

您正在配置对象内自动装配消息源。 MessageSource bean很可能还没有准备好。

我会尝试这样的事情:

private void yourCharacterInformationButton_Click(object sender, RoutedEventArgs e)
{
    if (AllFilesExist("NameData.xml", "ClassData.xml"))
    {
        // Omitted for brevity...
    }
}

答案 1 :(得分:0)

在applicationContext.xml中,添加以下内容:

<util:properties id="message" location="classpath:com/your/program/resources/message.properties" />

或如果使用基于java的配置:

@Bean(name = "message")
public PropertiesFactoryBean message() {
    PropertiesFactoryBean bean = new PropertiesFactoryBean();
    bean.setLocation(new ClassPathResource("com/your/program/resources/message.properties"));
    return bean;
}

创建一个字段变量并在Security Config中使用@Value注释,如下所示:

@Value(value = "#{'${flashmessage.loginsuccesful}'}")
private String loginSuccessMessage;

@Value("#{message['flashmessage.loginsuccesful']}")
private String loginSuccessMessage;

检查link以供参考。

答案 2 :(得分:0)

我认为这确实是MessageSource未准备好在Configuration对象中注入的问题。您的解决方案可能会起作用,并涉及使用@Value注释从application.properties文件中读取属性。我已经在AppConfig类中读过这个文件了:

@Configuration
@PropertySource(value= {"classpath:application.properties"})
public class AppConfig {
}

并在注入Environment对象的其他配置文件中访问所需的值:

@Autowired
private Environment env;

并在loginSuccesHandler()方法中:

String loginSuccessMessage = env.getProperty("flashmessage.loginsuccesful");

这确实有效,部分解决了这个问题。剩下的问题是财产声明:

flashmessage.loginsuccesful=You have been logged in succesfully!

需要从messages.properties移动到application.properties,而我使用属性的主要原因是将其与其他本地化消息一起定义,将来可能使用不同的语言。 但也许这根本不可能,因为此时不知道区域设置?

<强>更新 我通过将MessageSource bean的声明从Dispatcher servlet上下文(MvcConfig.java)移动到Root上下文(AppConfig.java)来解决了这个问题。 SecurityConfig类显然无法访问servlet上下文。

答案 3 :(得分:0)

在具有spring-boot-starter-thymeleaf依赖性的Spring Boot 2.3中对我有用的东西:

在我的@Configuration班上:

@Bean
public LocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.US);
    return slr;
}

@Bean
public MessageSourceAccessor getMessageSourceAccessor(MessageSource messageSource) {
    return new MessageSourceAccessor(messageSource);
}

然后在我要动态访问messages.properties中的值的任何bean中:

@Autowired
MessageSourceAccessor messageSourceAccessor;
...
messageSourceAccessor.getMessage(key)