【发布时间】:2014-12-12 07:17:33
【问题描述】:
我使用 Java Config 编写了一个小型 Spring MVC 应用程序,并使用 Spring Security 3.2.5 对其进行保护。它在 Tomcat 上运行良好,但在 JBoss EAP 6.2 上却不行。它成功部署在 JBoss 上,但是当我请求 Spring MVC 定义的任何页面并且在浏览器中出现 404 错误时,我收到此警告。
WARN [org.springframework.web.servlet.PageNotFound] (http-/127.0.0.1:8080-1) No mapping found for HTTP request with URI [/example-web/pages/login.jsp] in DispatcherServlet with name 'dispatcher'
由于使用了 Spring Security,对于任何需要经过身份验证的用户的请求,例如http://localhost:8080/example-web/start,Spring Security 重定向到 https://localhost:8443/example-web/login 那是我看到警告和 404 错误的时候。
在这里你可以看到我的代码:
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfiguration.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/*" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new HiddenHttpMethodFilter() };
}
}
这是我的 Spring MVC 配置:
@EnableWebMvc
@ComponentScan("com.spring.example.w.controller")
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/pages/");
resolver.setSuffix(".jsp");
return resolver;
}
}
下面是我的 Spring Security 配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.addFilter(myUsernamePasswordAuthenticationFilter())
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin/**").hasRole("Admin")
.antMatchers("/start/**").hasRole("Viewer")
.antMatchers("/user/**").hasRole("User")
.antMatchers("/**").hasRole("User")
.and()
.httpBasic().authenticationEntryPoint(loginUrlAuthenticationEntryPoint())
.and()
.logout()
.permitAll()
.and()
.requiresChannel()
.anyRequest().requiresSecure();
}
@Bean
public LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint(){
LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/login");
return loginUrlAuthenticationEntryPoint;
}
@Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider(){
ActiveDirectoryLdapAuthenticationProvider authProvider = new ActiveDirectoryLdapAuthenticationProvider(my_domain, my_url);
authProvider.setConvertSubErrorCodesToExceptions(true);
authProvider.setUseAuthenticationRequestCredentials(true);
authProvider.setUseAuthenticationRequestCredentials(true);
authProvider.setUserDetailsContextMapper(userDetailsContextMapper());
return authProvider;
}
@Bean
public UserDetailsContextMapper userDetailsContextMapper(){
CustomUserDetailsContextMapper myAuthoritiesPopulator = new CustomUserDetailsContextMapper();
return myAuthoritiesPopulator;
}
@Bean
public CustomUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter()
throws Exception {
CustomUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
usernamePasswordAuthenticationFilter.setAllowSessionCreation(true);
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);
usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login?error"));
usernamePasswordAuthenticationFilter.afterPropertiesSet();
return usernamePasswordAuthenticationFilter;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
}
然后是SecurityWebApplicationInitializer:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
和 RootConfig:
@Configuration
@ComponentScan
public class RootConfiguration {
}
以下是我为 SSL 配置 JBoss 的方式:
<subsystem xmlns="urn:jboss:domain:web:1.5" default-virtual-server="default-host" native="false">
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" redirect-port="8443"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" enable-lookups="false" secure="true">
<ssl name="ssl" password="<my_password>" certificate-key-file="c:\mykeystore.jks" protocol="TLSv1" verify-client="false"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="true">
<alias name="localhost"/>
<alias name="example.com"/>
</virtual-server>
</subsystem>
在部署期间,我可以在日志中看到请求确实被映射:
INFO [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] (ServerService Thread Pool -- 71) Mapped "{[/start],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView com.spring.example.w.controller.StartController.handleStart() throws javax.servlet.ServletException,java.io.IOException
INFO [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] (ServerService Thread Pool -- 71) Mapped URL path [/login] onto handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController]
INFO [org.springframework.web.context.ContextLoader] (ServerService Thread Pool -- 71) Root WebApplicationContext: initialization completed in 2530 ms
INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/example-web]] (ServerService Thread Pool -- 71) Initializing Spring FrameworkServlet 'dispatcher'
INFO [org.springframework.web.servlet.DispatcherServlet] (ServerService Thread Pool -- 71) FrameworkServlet 'dispatcher': initialization started
任何关于为什么我得到 404 错误的帮助,我们非常感谢这个警告。我要再次强调它正在 Tomcat 上运行。提前致谢。
【问题讨论】:
-
如果你直接请求 https URL 会得到 404 吗?通过 https 的其他请求是否有效?如果您从您的应用程序中删除 spring 安全性,它是否可以通过 https 工作?此外,您可能应该启用调试日志记录并尝试确定如何处理请求。
-
非常感谢您的回复。我删除了所有 Spring Security 配置以及 SSL。我尝试了一个简单的 Spring MVC 示例并将其与 Spring MVC 示例进行了比较。但是我得到了同样的错误,404。由于我的应用程序在 Tomcat 上工作得很好,我猜想 Tomcat 和 JBoss Servlet 容器之间的差异可能是原因。例如,我发现了这个帖子:link。虽然我已经将 Servlet 映射更改为“/*”而不是“/”。
-
我应该提到我可以在 JBoss 上使用 XML 设置运行我的应用程序(Spring MVC 安全性)。
-
好的。我想说您可能应该删除这个问题并创建一个具有最少信息量的新问题以及您可以进行的任何其他调试,因为如果没有 Spring Security,这里的大多数信息将不再相关。一般来说,在发布之前,您应该尝试将代码缩减为能够重现问题的最小应用程序。
-
我创建了另一个关于这个问题的帖子:stackoverflow.com/questions/26752124/…
标签: spring-mvc ssl jboss spring-security spring-java-config