Kno*_*ads 2 java spring web-applications spring-security spring-boot
我正在研究 Spring Security 的不同类实现。我知道我们将Authentication对象设置为SecurityContext ThreadLocal 对象,如下所示:
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
upat.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(upat);
Run Code Online (Sandbox Code Playgroud)
因此,基本上每个线程都有一个单独的 SecurityContext ThreadLocal 对象副本,它保存该线程的 Authentication 对象。到这里就好了。我也在我的 SecurityConfiguration 中将 SessionCreationPolicy 设置为 Stateless。以下是安全配置:
@Override
protected void configure(HttpSecurity http) throws Exception
{
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
final CorsConfigurer<HttpSecurity> cors = http.csrf().disable().cors().configurationSource(source);
final ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry exp =
cors.and().authorizeRequests();
exp.antMatchers("/getJWTToken/**").permitAll()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/rest/**").authenticated();
exp.and().exceptionHandling()
.authenticationEntryPoint(authEntryPoint())
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
// Add a filter to validate the tokens with every request
http.addFilterBefore(authRequestFilter(), UsernamePasswordAuthenticationFilter.class);
}
Run Code Online (Sandbox Code Playgroud)
但是,我对“线程”在这里的含义感到困惑?
对于以上两点,我也有这两点疑问。
if( SecurityContextHolder.getContext().getAuthentication() == null ) {
if( jwtTokenUtil.validateToken(jwtToken, userObj) )
{
if( userObj == null )
{
response.setStatus(401);
return;
}
else
{
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(userObj, null,userObj.getAuthorities());
upat.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(upat);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里对线程(ThreadLocal SecurityContext)的解释可能是错误的。需要帮忙。
SecurityContextHolder、SecurityContext 和身份验证对象
\n默认情况下,SecurityContextHolder使用 aThreadLocal来存储这些详细信息,这意味着安全上下文始终可供同一执行线程中的方法使用。ThreadLocal以这种方式使用 a是quite safe if care is taken to clear the thread after the present principal\xe2\x80\x99s request is processed. 当然,Spring Security 会自动为您处理这个问题,因此无需担心。
某些应用程序\xe2\x80\x99t 完全适合使用ThreadLocal,因为它们使用线程的特定方式。例如,Swing 客户端可能希望 Java 虚拟机中的所有线程使用相同的安全上下文。SecurityContextHolder可以在启动时配置策略来指定您希望如何存储上下文。对于独立应用程序,您将使用该SecurityContextHolder.MODE_GLOBAL策略。其他应用程序可能希望安全线程生成的线程也采用相同的安全身份。这是通过使用 来实现的SecurityContextHolder.MODE_INHERITABLETHREADLOCAL。您可以通过两种方式更改默认模式SecurityContextHolder.MODE_THREADLOCAL。
第一个是设置系统属性,第二个是调用 上的静态方法SecurityContextHolder。大多数应用程序不需要更改默认值,但如果需要,请查看 SecurityContextHolder 的 JavaDoc 以了解更多信息。
在 Spring Security 中,存储SecurityContext请求之间的信息的责任落在了SecurityContextPersistenceFilter,它默认将上下文存储为HTTP 请求HttpSession之间的属性。它将上下文恢复到每个请求,并且最重要的是,在请求完成时清除 SecurityContextHolderSecurityContextHolder
许多其他类型的应用程序(例如,无状态 RESTful Web 服务)不使用HTTP 会话,并将对每个请求重新进行身份验证。SecurityContextPersistenceFilter然而,将 包含在链中以确保SecurityContextHolder在每次请求后清除仍然很重要。
会话管理
\n.sessionManagement()\n .sessionCreationPolicy(SessionCreationPolicy.STATELESS)\nRun Code Online (Sandbox Code Playgroud)\n将导致 Spring Security 使用NullSecurityContextRepository, 而不是默认的HttpSessionSecurityContextRepository.
这是一个简单的实现,因为它不会将任何内容保存到 HTTP Session,并且对于每个请求,创建一个全新的空 SecurityContext,因此没有存储的身份验证等。
\n更新
\n\n\n这意味着,如果会话策略是无状态的,则以下条件始终为真。if( SecurityContextHolder.getContext().getAuthentication()\n== null )
\n
是的,除非您在调用条件之前设置了身份验证,否则您将获得空身份验证。如果您使用 JWT 令牌,您可以验证如下内容并可以设置安全上下文。
\n@Override\npublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)\n throws IOException, ServletException {\n HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;\n HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;\n String jwt = resolveToken(httpServletRequest);\n\n if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {\n Authentication authentication = this.tokenProvider.getAuthentication(jwt);\n SecurityContextHolder.getContext().setAuthentication(authentication);\n ...\n }\n filterChain.doFilter(servletRequest, servletResponse);\n}\n\nprivate String resolveToken(HttpServletRequest request){\n String bearerToken = request.getHeader(AUTHORIZATION_HEADER);\n if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {\n return bearerToken.substring(7);\n }\n return null;\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4130 次 |
| 最近记录: |