我的项目有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