pas*_*mes 6 spring spring-mvc spring-security servlet-3.0 spring-java-config
在几个博客文章和SO问题中相对较好地讨论了这个问题.然而,我无法找到一个专门解决java配置问题的人.我怀疑我在java配置文件中做错了,因为我发现一些帖子表明可以通过删除调试XML标签来解决问题(https://jira.springsource.org/browse/ SEC-1885).
我正在使用Spring安全性的3.2.0.RELEASE和Spring框架的3.2.6.RELEASE.在spring security/mvc配置和自定义AuthenticationProvider中使用的主文件下面.
WebConfig:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.mypackage"})
@ImportResource( { "classpath:/spring-data.xml", "classpath:/trace-context.xml" })
@EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean(destroyMethod = "shutdown")
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("target/temp.db");
}
@Bean
public RepositoryInitializer repositoryInitializer() {
return new RepositoryInitializer();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
return cookieLocaleResolver;
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
// if true, the key of the message will be displayed if the key is not
// found, instead of throwing a NoSuchMessageException
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
// # -1 : never reload, 0 always reload
messageSource.setCacheSeconds(0);
return messageSource;
}
}
Run Code Online (Sandbox Code Playgroud)
WebInitializer:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return new Filter[] { characterEncodingFilter, new SiteMeshFilter()};
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
//servletContext.addListener(new HttpSessionEventPublisher());
}
}
Run Code Online (Sandbox Code Playgroud)
WebSecurityConfig:
@Configuration
@EnableWebSecurity
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().permitAll();
// .antMatchers("/", "/login").permitAll()
// .anyRequest().authenticated();
http
.formLogin()
.defaultSuccessUrl("/hello")
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll();
http
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.authenticationProvider(new ApplicationAuthenticationProvider());
}
}
Run Code Online (Sandbox Code Playgroud)
WebSecurityInitializer:
public class WebSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
Run Code Online (Sandbox Code Playgroud)
的AuthenticationProvider:
@Component(value = "authenticationProvider")
public class ApplicationAuthenticationProvider implements AuthenticationProvider {
@Autowired
public UserService userService;
public ApplicationAuthenticationProvider() {}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
User user = userService.loadUserByUsername(username);
if (user == null) {
throw new BadCredentialsException("Username not found.");
}
if (!password.equals(user.getPassword())) {
throw new BadCredentialsException("Wrong password.");
}
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
UserService:
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public User loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepository.findByUsername(username);
}
}
Run Code Online (Sandbox Code Playgroud)
Spring在构建应用程序上下文时(在应用程序初始化期间)抛出异常:
[ERROR] [main 11:53:37] (FrameworkServlet.java:initServletBean:467) Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public com.evidencefactory.service.UserService com.evidencefactory.security.ApplicationAuthenticationProvider.userService; nested exception is java.lang.IllegalArgumentException: Can not set com.evidencefactory.service.UserService field com.evidencefactory.security.ApplicationAuthenticationProvider.userService to sun.proxy.$Proxy71
Run Code Online (Sandbox Code Playgroud)
我不明白它为什么会发生,但如果我UserDetailsService从UserService类中删除接口实现,那么应用程序就会成功启动.但是,当ApplicationAuthenticationProviderSpring调用时,UserService它不会自动装入它,并且应用程序抛出NullPointerException.
java.lang.NullPointerException
at com.evidencefactory.security.ApplicationAuthenticationProvider.authenticate(ApplicationAuthenticationProvider.java:33)
Run Code Online (Sandbox Code Playgroud)
弄清楚如何将其付诸实施,尽管仍有一些问题没有得到解决.
1)我仍然不知道UserService实现时Spring上下文初始化失败的原因UserDetailsService.鉴于我没有看到它的使用,因为我正在使用自定义AuthenticationProvider,我刚刚删除了这个实现,现在一切正常.据我所知(从我第一次初读Spring Security参考文档时可以理解)提供自定义AuthenticationProvider或UserDetailsService实现是唯一的选择.
2)正如其中一位受访者(@Sotirios Delimanolis)所注意到的那样,我ApplicatinoAuthenticationProvider手动实例化,因为它不是由Spring管理的,所以这个实例不会有UserService自动装入它的实例.基于此,我改为WebSecurityConfig获得一个自动装配的实例,ApplicationAuthenticationProvider如下所示:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ApplicationAuthenticationProvider authenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.authenticationProvider(authenticationProvider);
}
}
Run Code Online (Sandbox Code Playgroud)
这还不够,因为ApplicationAuthenticationProvider没有自动装入WebSecurityConfig.基于此链接Spring Security 3.1.3 @Autowired not Work在使用WebApplicationInitializer时我注意到这是因为安全配置也应该有组件扫描声明.添加@ComponentScan(basePackages = {"com.mypackage"})到WebSecurityConfig解决这个问题.
| 归档时间: |
|
| 查看次数: |
10402 次 |
| 最近记录: |