Spring Security 4.x,Dynamic InvalidSessionUrl

时间:2015-05-11 19:58:29

标签: java spring security spring-security

我的项目有2个用户角色:[ADMIN,COURT]和未经身份验证的(匿名?)用户。 ADMIN具有超级管理员访问权限,即全局访问权限。 COURT可以访问特定页面。 ADMIN和COURT都经过身份验证。

问题是会话超时需要针对这三个群体进行不同的处理:ADMIN和COURT用户需要重定向到各自的登录页面,未经身份验证的会话需要定向到上下文主页(/ xyz) / home)基于之前的背景。

我已经搜索了这个主题,似乎无法提及这个概念和解决方案。据我所知,研究中会话管理无效会话URL控制此行为,但我需要动态值,以便我可以控制着陆点。

我的代码:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
private MongoUserService mongoUserService;

@Autowired
private LoginAuthenticationEntryPoint loginEntryPoint;

@Autowired
private AuthenticationFailureHandler loginFailureHandler;

@Autowired
private LogoutSuccessHandler logoutSuccessHandler;

@Override
public void configure(WebSecurity web) throws Exception {
    web
        .ignoring()
            .antMatchers("/assets/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .exceptionHandling()
            .authenticationEntryPoint(loginEntryPoint)
            .accessDeniedPage("/403")
        .and()
            .authorizeRequests()
                .antMatchers("/admin/login**").permitAll()
                .antMatchers("/court/login**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/**/court/**").hasAnyRole("ADMIN","COURT")
            .anyRequest()
                .permitAll()
        .and()
            .formLogin()
                .loginProcessingUrl("/dologin")
                .failureHandler(loginFailureHandler)
                .usernameParameter("username")
                .passwordParameter("password")
        .and()
            .logout()
                .logoutUrl("/dologout")
                .logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(false)
        .and()
            .sessionManagement()
                .invalidSessionUrl("/")
                .maximumSessions(1)
        ;
}

@Override
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(mongoUserService).passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Component
public class LoginAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {

    @Autowired
    public LoginAuthenticationEntryPoint() {
        // LoginUrlAuthenticationEntryPoint requires a default
        super("/");
    }

    /**
     * @param request   the request
     * @param response  the response
     * @param exception the exception
     * @return the URL (cannot be null or empty; defaults to {@link #getLoginFormUrl()})
     */
    @Override
    protected String determineUrlToUseForThisRequest(HttpServletRequest request, HttpServletResponse response,
                                                 AuthenticationException exception) {
        String requestUrl = request.getRequestURI();
        System.out.println("in LoginAuthenticationEntryPoint, requestUrl = " + requestUrl);
        if (requestUrl.indexOf("/admin") != -1) {
            return "/admin/login";
        }
        else if (requestUrl.indexOf("/court") != -1) {
            return "/court/login";
        }
        else {
            return "/admin/login";
        }
    }
}

@Component
public class AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Autowired
    public AuthenticationFailureHandler() {
        super();
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                    AuthenticationException exception) throws IOException, ServletException {
        setDefaultFailureUrl(getFailureUrl(request));
        super.onAuthenticationFailure(request, response, exception);
    }

    private String getFailureUrl(HttpServletRequest request) {
        String refererUrl = request.getHeader("Referer");
        System.out.println("in AuthenticationFailureHandler, referrerUrl: " + refererUrl);
        if (refererUrl.indexOf("/admin") != -1) {
            return "/admin/login?err=1";
        }
        else if (refererUrl.indexOf("/court") != -1) {
            return "/court/login?err=1";
        }
        else {
            return "/admin/login?err=1";
        }
    }
}

@Component
public class LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {

    @Autowired
    public LogoutSuccessHandler() {
        super();
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, 
                                Authentication authentication) throws IOException, ServletException {
        setDefaultTargetUrl(request.getHeader("Referer"));
        handle(request, response, authentication);
    }
}
}

更新:

当我尝试使用自定义ConcurrentSessionFilter时,我收到了一个异常。这是代码,下面是生成的堆栈跟踪:

@Bean
public ConcurrentSessionFilter customConcurrentSessionFilter() {
    return new CustomConcurrentSessionFilter();
}

public class CustomConcurrentSessionFilter extends ConcurrentSessionFilter {

    protected String determineExpiredUrl(HttpServletRequest request, SessionInformation info) {
        return "something here";
    }
}

例外:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customConcurrentSessionFilter' defined in class path resource [com/cii/config/SecurityConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: SessionRegistry required
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4770)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: SessionRegistry required
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.security.web.session.ConcurrentSessionFilter.afterPropertiesSet(ConcurrentSessionFilter.java:85)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
    ... 21 more

0 个答案:

没有答案