Spring mvc 在Spring安全配置中访问messages.properties
我最近切换到SpringSecurity来处理我的Web应用程序的登录、注销和基于角色的访问。我使用flash消息获取信息和错误消息,并希望在成功登录和注销后显示此类消息 在JSP文件中,这些消息使用以下代码显示:Spring mvc 在Spring安全配置中访问messages.properties,spring-mvc,spring-security,Spring Mvc,Spring Security,我最近切换到SpringSecurity来处理我的Web应用程序的登录、注销和基于角色的访问。我使用flash消息获取信息和错误消息,并希望在成功登录和注销后显示此类消息 在JSP文件中,这些消息使用以下代码显示: <c:if test = "${not empty flashmessage_error}" > <div class="alert alert-danger"><c:out value="${flashmessage_error}" />
<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>
我的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文件中的正确消息。相反,字符串“not found”在登录后显示为flash消息。
在下面的一行中,我尝试使用注入的MessageSource通过message键查找消息,但显然没有找到它,并且显示了回退消息:
String loginSuccessMessage = messageSource.getMessage("flashmessage.loginsuccesful", null, "not found", null);
MessageSourceBean在MvcConfig文件中定义,如下所示,用于在JSP文件中显示消息时工作良好,但它似乎无法在Spring安全配置文件中自动连接以获得所需的flash消息
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
你知道我怎样才能做到这一点吗 您正在配置对象内自动连接消息源。MessageSourcebean很可能还没有准备好 我想试试这样的东西:
public class FlashMessageAuthSuccessHandler extends
SavedRequestAwareAuthenticationSuccessHandler {
@Value(${flashmessage.loginsuccesful})
private String flashMessage;
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);
}
}
在applicationContext.xml中,添加以下内容:
<util:properties id="message" location="classpath:com/your/program/resources/message.properties" />
创建字段变量并在安全配置中使用@Value注释,如下所示:
@Value(value = "#{'${flashmessage.loginsuccesful}'}")
private String loginSuccessMessage;
或
检查引用。我认为这确实是MessageSource未准备好注入配置对象的问题。您的解决方案可能会起作用,包括使用@Value注释从application.properties文件中读取属性。我已在AppConfig类中读取此文件:
@Configuration
@PropertySource(value= {"classpath:application.properties"})
public class AppConfig {
}
并访问注入环境对象的其他配置文件之一中的所需值:
@Autowired
private Environment env;
在loginsAccessHandler()方法中:
这确实有效,部分解决了问题。剩下的问题是财产声明:
flashmessage.loginsuccesful=You have been logged in succesfully!
需要从messages.properties移动到application.properties,而我使用属性的主要原因是将其与其他本地化消息一起定义,将来可能使用不同的语言。
但也许这根本不可能,因为此时不知道区域设置
更新:
通过将MessageSourcebean的声明从DispatcherServlet上下文(MvcConfig.java)移动到根上下文(AppConfig.java),我解决了这个问题。SecurityConfig类显然无法访问servlet上下文。在Spring Boot 2.3中,使用
Spring Boot starter thymeleaf
依赖项对我起作用的是什么:
在我的@配置
类中:
@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)
String loginSuccessMessage = env.getProperty("flashmessage.loginsuccesful");
flashmessage.loginsuccesful=You have been logged in succesfully!
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
@Bean
public MessageSourceAccessor getMessageSourceAccessor(MessageSource messageSource) {
return new MessageSourceAccessor(messageSource);
}
@Autowired
MessageSourceAccessor messageSourceAccessor;
...
messageSourceAccessor.getMessage(key)