Java Spring Security 4.x,动态InvalidSessionUrl
我的项目有两个用户角色:[管理员,法庭]和未经验证的匿名用户?用户。管理员具有超级管理员访问权限,即全局访问权限。法院有权访问特定页面。管理员和法庭都经过认证 问题在于,对于这三种人群,需要对会话超时进行不同的处理:管理员和法庭用户需要重新定向到各自的登录页面,未经验证的会话需要根据以前的上下文定向到上下文主页/xyz/home 我在谷歌上搜索过这个话题,但似乎找不到关于这个概念和解决方案的提及。就我从研究中所见,会话管理无效会话url控制着这种行为,但我需要这里的动态值,以便我可以控制登录点 我的代码:Java Spring Security 4.x,动态InvalidSessionUrl,java,spring,security,spring-security,Java,Spring,Security,Spring Security,我的项目有两个用户角色:[管理员,法庭]和未经验证的匿名用户?用户。管理员具有超级管理员访问权限,即全局访问权限。法院有权访问特定页面。管理员和法庭都经过认证 问题在于,对于这三种人群,需要对会话超时进行不同的处理:管理员和法庭用户需要重新定向到各自的登录页面,未经验证的会话需要根据以前的上下文定向到上下文主页/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);
}
}
}
更新:
当我尝试miplement自定义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
首先,LogoutSuccessHandler和AuthenticationFailureHandler有缺陷,它们在高并发环境中无法工作。现在,您每次都在重置默认URL。假设用户和管理员同时进入,一个更改会覆盖另一个更改,用户可能会转到管理员页面,反之亦然。但要回答您的问题,请创建一个自定义ConcurrentSessionFilter并重写DetermineeExpireDurl方法。好的,这很有意义。然而,我在实现自定义ConcurrentSessionFilter时遇到了问题;我在初始化时看到异常。过去几天我一直在冒烟,如果这件事简单/直接,我深表歉意。你能给我一个更明确的例子吗?请加上错误。使用自定义类时,您不能使用sessionManagement方法来配置内容,但必须手动完全配置筛选器,并使用addFilterBefore方法将其添加。上面包含代码和错误