Я следую учебнику о JWT в контексте пружинного реагирования (webflux).
Генерация токенов работает нормально, однако авторизация не работает, когда я использую Authorization
с bearer
Вот что я сделал:
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig{
@Autowired private JWTReactiveAuthenticationManager authenticationManager;
@Autowired private SecurityContextRepository securityContext;
@Bean public SecurityWebFilterChain configure(ServerHttpSecurity http){
return http.exceptionHandling()
.authenticationEntryPoint((swe , e) -> {
return Mono.fromRunnable(()->{
System.out.println( "authenticationEntryPoint user trying to access unauthorized api end points : "+
swe.getRequest().getRemoteAddress()+
" in "+swe.getRequest().getPath());
swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
});
}).accessDeniedHandler((swe, e) -> {
return Mono.fromRunnable(()->{
System.out.println( "accessDeniedHandler user trying to access unauthorized api end points : "+
swe.getPrincipal().block().getName()+
" in "+swe.getRequest().getPath());
swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
});
})
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.authenticationManager(authenticationManager)
.securityContextRepository(securityContext)
.authorizeExchange()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.pathMatchers("/auth/login").permitAll()
.anyExchange().authenticated()
.and()
.build();
}
Как видите, я хочу просто отклонить все неавторизованные запросы, кроме запросов входа в систему или опций.
Логин работает нормально, и я получаю токен.
Но попытка выхода из системы (твик, который я реализовал, чтобы сделать его полным состоянием, так как я только учусь) не работает.
Вот мой контроллер выхода из системы:
@RestController
@RequestMapping(AuthController.AUTH)
public class AuthController {
static final String AUTH = "/auth";
@Autowired
private AuthenticationService authService;
@PostMapping("/login")
public Mono<ResponseEntity<?>> login(@RequestBody AuthRequestParam arp) {
String username = arp.getUsername();
String password = arp.getPassword();
return authService.authenticate(username, password);
}
@PostMapping("/logout")
public Mono<ResponseEntity<?>> logout(@RequestBody LogoutRequestParam lrp) {
String token = lrp.getToken();
return authService.logout(token);
}
}
Запрос на выход из системы следующий:
Как указано на изображениях выше, я считаю, что у меня все хорошо, но я получаю сообщение об ошибке:
authenticationEntryPoint пользователь пытается получить доступ к неавторизованным конечным точкам API: /127.0.0.1:45776 в / auth / logout
Вот мой контекст безопасности:
/**
* we use this class to handle the bearer token extraction
* and pass it to the JWTReactiveAuthentication manager so in the end
* we produce
*
* simply said we extract the authorization we authenticate and
* depending on our implementation we produce a security context
*/
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
@Autowired
private JWTReactiveAuthenticationManager authenticationManager;
@Override
public Mono<SecurityContext> load(ServerWebExchange swe) {
ServerHttpRequest request = swe.getRequest();
String authorizationHeaderContent = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if( authorizationHeaderContent !=null && !authorizationHeaderContent.isEmpty() && authorizationHeaderContent.startsWith("Bearer ")){
String token = authorizationHeaderContent.substring(7);
Authentication authentication = new UsernamePasswordAuthenticationToken(token, token);
return this.authenticationManager.authenticate(authentication).map((auth) -> {
return new SecurityContextImpl(auth);
});
}
return Mono.empty();
}
@Override
public Mono<Void> save(ServerWebExchange arg0, SecurityContext arg1) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Я не вижу ни одной обнаруженной проблемы или ошибки. Где ошибка?