gpt4 book ai didi

javascript - Spring Security Authentication 对象对于 Spring SseEmitter 为 null

转载 作者:行者123 更新时间:2023-11-29 19:03:42 30 4
gpt4 key购买 nike

我有一个 Spring Controller 方法调用 SseEmitter 将服务器发送的事件推送到浏览器。在浏览器中,为 SSE url 创建 EventSource 的 javascript 是从主页运行的。主页本身需要使用基于 Spring Security 表单的身份验证完成的身份验证。因此,登录页面在成功验证后将定向到主页。但是,服务器发送事件方法中的验证对象为null。我知道我不正确的 Spring Security 配置导致了这个问题,但不知道如何解决!!

下面是我使用的安全配置

@Configuration
@EnableWebMvcSecurity
public class UCFSecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
@Qualifier("epUser")
private UserDetailsService userDetailsService;

@Autowired
private AuthenticationSuccessHandler successHandler;
....
....
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/**").authenticated()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.htm").failureUrl("/error.htm")
.loginProcessingUrl("/spring_sec_auth.htm")
.usernameParameter("username").passwordParameter("password").permitAll()
.successHandler(successHandler)
.and()
.logout()
//.logoutSuccessUrl("/login.htm?logout")
.invalidateHttpSession(true)
.and().csrf().disable();

}
....
....
}

The SSE method below calls userActivityFeed() in UserActivityService which uses Authentication object from SecurityContextHolder.getContext().getAuthentication() which throws an NPE!!!

@Controller
public class UserActivityController {

@Autowired
private UserActivityService userActivityService;

@RequestMapping("/userActivity")
public ResponseBodyEmitter activityFeed() {

final SseEmitter emitter = new SseEmitter();
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> {
try {
emitter.send(userActivityService.userActivityFeed() , MediaType.TEXT_PLAIN);
Thread.sleep(UCFConstants.USR_ACTV_REFRESH_PERIOD);

} catch (Exception e) {
e.printStackTrace();
emitter.completeWithError(e);
return;
}
emitter.complete();
});
service.shutdown();
return emitter;
}
}

创建 SSE EventSource 对象的 Javascript

<script type="text/javascript">
var source = new EventSource("/MyApp/rest/userActivity");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data
+ "<br>";
};
</script>

我的应用程序 web.xml

 <servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

最佳答案

查看 SecurityContextHolder.getContext() 实现。在引擎盖下,它使用 ThreadLocalSecurityContextHolderStrategy 策略来保存您当前的安全上下文。这意味着当前安全上下文只能从请求线程获得。而您的 userActivityFeed() 实际上是在单独的线程中执行的,这就是为什么您在调用 SecurityContextHolder.getContext().getAuthentication() 时遇到 NPE 的原因。

要完成所有这些工作,您可以在 Controller 方法中更早地获取当前用户并将其传递给 userActivityFeed()

关于javascript - Spring Security Authentication 对象对于 Spring SseEmitter 为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44624833/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com