可能答案很简单:如何在spring security中手动注销当前登录的用户?打电话是否足够:
SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
Run Code Online (Sandbox Code Playgroud)
?
我正在使用 spring security 来实现程序化的手动用户登录。我有一个场景,我已经确定了用户的身份,并希望让他们登录。我不知道他们的密码,因此无法使用常规登录代码路径,您将表单提交到 url,即通过 servlet 拦截Filter,完成所有的 auth+session 魔术。
我搜索过,似乎大多数人创建了自己的Authentication对象,然后通过以下方式告诉 spring:
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(user, "", user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
Run Code Online (Sandbox Code Playgroud)
确实,这是有效的。Spring 甚至为我将其放入会话中,使后续的 http 请求保持其身份验证状态。
但是,我觉得这是一个肮脏的黑客。我将提供一些细节,希望能给出与setAuthentication()在控制器内部使用以实现手动登录相关的问题的具体示例:
给出一个想法,我的配置是:
httpSecurity
.authorizeRequests()
.antMatchers("/test/**").permitAll()
.antMatchers("/admin/**", "/api/admin/**").hasRole("USER_SUPER_ADMIN")
.and()
.formLogin()
.loginPage("/sign-in?sp")
.loginProcessingUrl("/api/auth/sign-in")
.successHandler(createLoginSuccessHandler())
.failureHandler(createLoginFailureHandler())
.permitAll()
.and()
.logout()
.logoutUrl("/api/auth/sign-out")
.logoutSuccessHandler(createLogoutSuccessHandler())
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry)
;
Run Code Online (Sandbox Code Playgroud)
上述配置中的要点:
我单步执行代码以查看 spring 如何处理表单登录。正如预期的那样,HttpSecurity当我使用表单登录时,Spring 执行了我的配置告诉它执行的所有会话/登录功能。但是,当我通过 进行自己的自定义/手动登录时SecurityContextHolder.getContext().setAuthentication(),它没有任何这些功能。这是因为 spring 在 servlet 内部完成了所有的会话/登录功能Filter,而我的编程代码不能真正调用过滤器。现在,我可以尝试添加缺少的功能自己,复制其代码:我看到弹簧过滤器用途:ConcurrentSessionControlAuthenticationStrategy,ChangeSessionIdAuthenticationStrategy …