【发布时间】:2015-10-09 16:51:23
【问题描述】:
使用 Spring-Boot 1.1.17, Spring-MVC 和 Spring-Security:
我希望允许未经身份验证的用户(访问者)访问多个子域。例如:
- mysite.com/customerA
- mysite.com/customerB
如果尝试了无效的客户站点,那么我的控制器将抛出异常或重定向回 / (mysite.com/) 自然域的其他部分 (mysite.com/customerA/myaccount) 将需要登录。
我还没有真正弄清楚如何使用 spring security 和 spring-mvc 来做到这一点。到目前为止,这是我正在尝试的:
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers( "/**/" ).permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/wizard").permitAll()
.antMatchers("/menu").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/fonts/**").permitAll()
.antMatchers("/libs/**").permitAll();
http
.formLogin()
.loginPage("/loginPage")
.permitAll()
.loginProcessingUrl("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/?tab=success")
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.permitAll()
.and()
.csrf();
http
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired")
.maxSessionsPreventsLogin(true)
.and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/");
http
.authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService( customUserDetailsService ).passwordEncoder( encoder );
}
@Override
public void configure(WebSecurity security){
security.ignoring().antMatchers("/css/**","/fonts/**","/libs/**");
}
}
还有我的主页控制器:
@Controller
@RequestMapping("/{officeName}/")
public class HomeController {
private AuthenticatedUser getVisitor(@PathVariable String officeName) {
.. do something with the office if found, redirect otherwise
if (!StringUtils.isEmpty(officeName)) {
Office office = officeService.findByName( officeName );
return office.getUrl();
}
return "/";
}
当我尝试访问该网址时,我收到以下错误:
o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/customerA/]
s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /customerA/
s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/customerA/]
o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/customerA/] are [/**]
o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/customerA/] are {}
o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/customerA/] to HandlerExecutionChain with handler [org.springframework.web.servlet.resource.ResourceHttpRequestHandler@2f295527] and 1 interceptor
o.s.web.servlet.DispatcherServlet : Last-Modified value for [/customerA/] is: -1
o.s.w.s.r.ResourceHttpRequestHandler : Trying relative path [customerA] against base location: ServletContext resource [/]
o.s.w.s.r.ResourceHttpRequestHandler : Trying relative path [customerA] against base location: class path resource [META-INF/resources/]
o.s.w.s.r.ResourceHttpRequestHandler : Trying relative path [customerA] against base location: class path resource [resources/]
o.s.w.s.r.ResourceHttpRequestHandler : Trying relative path [customerA] against base location: class path resource [static/]
o.s.w.s.r.ResourceHttpRequestHandler : Trying relative path [customerA] against base location: class path resource [public/]
o.s.w.s.r.ResourceHttpRequestHandler : No matching resource found - returning 404
我尝试添加这个 ServletRegistrationBean:
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean( dispatcherServlet );
registration.addUrlMappings("/", "/testCustomer/*" );
for ( Office office : officeService.findAllActiveOffices() ) {
registration.addUrlMappings( office.getUrl() + "/*" );
}
return registration;
}
但这似乎只有在应用程序在启动时就知道客户的情况下才有效,而不是在客户注册的情况下动态地工作。
有没有办法配置它来处理这些类型的通配符?
【问题讨论】:
-
这是一个带有
@PathVariable绑定的私有方法(可能不适用于Spring MVC)? -
@Dave - 哎呀,谢谢你的收获。不幸的是,这对我的问题并没有真正的影响。 ServletRegistrationBean 方法似乎是一个开始,无论如何在运行时动态更新 ServletRegistrationBean(即 - 新客户注册)?
-
如果你必须这样做,我真的不明白用例。 Spring MVC 可以动态匹配路径(就像您尝试使用
@PathVariable一样),因此您真的应该使用该功能。 -
戴夫是对的。顺便说一下。密码编码器应该是一个 bean。并且antMatchers是一个可变参数方法,所以,可以只写2的前10行。如果
"/css/**"、"/fonts/**"、"/libs/**"已经被忽略,则需要在antMatchers中添加它们以获得permitAll。和戴夫一样,我不了解用例。这已经是@PathVariable的标称行为了。你为什么需要那个? -
我还以为 Spring-MVC 会处理动态 URL,但是没有 ServletRegistrationBean,URL 将不会呈现。我假设这是 spring-security 阻止它。
标签: spring-security spring-boot