我正在使用 Spring Boot 3.2.0 和 Java 17 开发一个遵循微服务架构的应用程序。我有一个服务 -
AuthService
用于身份验证目的。用户的登录请求将通过 API 网关路由到 AuthService
,并在提供有效的用户凭据后获得 JWT 令牌。
现在,用户拥有有效的 JWT 令牌。通过将此令牌以
Bearer token
格式放入请求标头中,用户可以向任何其他服务(即,employeeService、hospitalService...;我将这些服务称为 OtherService
)发出 http 请求。我不想给令牌验证代码带来负担。相反,在 OtherService
-> AuthService
处有一个 API 端点。此端点将验证 jwt 令牌并返回 cusotm /auth/validate
对象。简而言之,工作流程是这样的 - 如果用户想查看员工列表,第一个用户将提供用户名、密码。这将由 UserDetails
验证并返回
JWT令牌。然后,用户将使用此令牌向employeeService 发出请求。
AuthService
中将有一个过滤器,它将检查请求标头中是否有任何授权令牌,并对 EmployeeService
进行其余调用以从中获取 UserDetail对象。 [P.S.我是 Spring Security 的新手;我不确定这种方法是否理想]
下面,我提供了
AuthService
的代码部分。
EmployeeService
注意:我在这里没有定义任何
@RefreshScope
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class ApplicationSecurity {
private final AppSecurityFilter appSecurityFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.cors(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(appSecurityFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/health")
.permitAll()
.anyRequest()
.authenticated())
.build();
}
}
或
AuthenticationManager
AuthenticationProvider
,因为我没有在 bean
中从数据库验证或获取用户对象,而是调用 EmployeeService
从 AuthService
执行此操作。 2。应用程序安全过滤器
AppSecurityFilter
所以,我面临的问题是;即使我在请求标头中设置了授权令牌;
@AllArgsConstructor
@Component
public class AppSecurityFilter extends OncePerRequestFilter {
private static String AUTH_SERVER_VALIDATE_TOKEN_URL = "http://AUTH-SERVICE/auth/api/v1/validate";
private RestTemplate restTemplate;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String header = request.getHeader(AUTHORIZATION);
if (isEmpty(header) || !header.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
ResponseEntity<AuthResponseDto> authResponse = // get userDetails form authService via restTeamplate post call
UserResponseDto user = authResponse.getBody().getUserResponseDto();
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(
user,
null,
user.getAuthorities()
)
);
filterChain.doFilter(request, response);
}
}
应用程序将请求重定向到Spring的默认登录页面。此外,
EmployeeService
永远不会调用。我在这里缺少什么,完成这项工作需要哪些必要步骤?
AppSecurityFilter
类中添加了
@RefreshScope
注释而发生的。 (p.s.我一开始以为这与问题无关,所以没有在问题中添加这个注释). 如果将来有人偶然发现此类问题,请在此处添加我的发现。
投入日志后,我发现如果添加了
ApplicationSecurity
那么在应用程序启动时会有两个独立的
@RefreshScope
日志 -DefaultSecurityFilterChain
如您所见,日志的第二行没有我配置的自定义过滤器。
如果我从类中删除了
line1: o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [
DisableEncodeUrlFilter,
WebAsyncManagerIntegrationFilter,
SecurityContextHolderFilter,
HeaderWriterFilter,
LogoutFilter,
AppSecurityFilter, <------------------- my custom filter added
RequestCacheAwareFilter,
SecurityContextHolderAwareRequestFilter,
AnonymousAuthenticationFilter,
SessionManagementFilter,
ExceptionTranslationFilter,
AuthorizationFilter
]
line2: o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [
DisableEncodeUrlFilter,
WebAsyncManagerIntegrationFilter,
SecurityContextHolderFilter,
HeaderWriterFilter,
CorsFilter,
CsrfFilter,
LogoutFilter,
UsernamePasswordAuthenticationFilter,
DefaultLoginPageGeneratingFilter,
DefaultLogoutPageGeneratingFilter,
BasicAuthenticationFilter,
RequestCacheAwareFilter,
SecurityContextHolderAwareRequestFilter,
AnonymousAuthenticationFilter,
ExceptionTranslationFilter,
AuthorizationFilter
]
注释,则仅打印一行
@RefreshScope
-日志
DefaultSecurityFilterChain
通过从
DefaultSecurityFilterChain : Will secure any request with [
DisableEncodeUrlFilter,
WebAsyncManagerIntegrationFilter,
SecurityContextHolderFilter,
HeaderWriterFilter,
LogoutFilter,
AppSecurityFilter, <------------------ my custom filter
RequestCacheAwareFilter,
SecurityContextHolderAwareRequestFilter,
AnonymousAuthenticationFilter,
SessionManagementFilter,
ExceptionTranslationFilter,
AuthorizationFilter
]
类中删除
@RefreshScope
,一切都会按预期进行。为什么我首先添加ApplicationSecurity
?
我正在从 ConfigServer 读取一些属性。为什么添加
@RefreshScope
会使 Spring Security 回退到默认配置?
我还没想明白。