Я использую SpringBoot
с Eureka
Server. У меня есть пользователи microservice
, одна eureka server
и одна springcloud apigateway
папка. Вот полный исходный код
В моем users microservice's controller
у меня есть код ниже
@RestController
@RequestMapping("/users")
public class UsersController {
@Autowired
private Environment env;
@Autowired
UsersService usersService;
@GetMapping("/status/check")
public String status(){
System.out.println("hereeeeeeeeeee");
return "Working "+env.getProperty("local.server.port");
}
@PostMapping
public ResponseEntity<CreateUserResponseModel> createUser(@Valid @RequestBody CreateUserRequestModel userDetails) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserDto userDto = modelMapper.map(userDetails, UserDto.class);
UserDto createdUser = usersService.createUser(userDto);
CreateUserResponseModel body = modelMapper.map(createdUser, CreateUserResponseModel.class);
return ResponseEntity.status(HttpStatus.CREATED).body(body);
}
}
Теперь конечная точка Get API возвращается в виде 403 Forbidden, конечная точка публикации работает нормально.
Ниже скриншот ошибки
Я определил класс AuthorizationHeaderFilter
в apigateway
, который используется для декодирования jwt
, который я отправляю в конечной точке GET Api, и он правильно декодирует JWT
@Component
public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory<AuthorizationHeaderFilter.Config>{
@Autowired
private Environment environment;
public AuthorizationHeaderFilter(){
super(Config.class);
}
public static class Config{
}
@Override
public GatewayFilter apply(Config config) {
return (exchange,chain)->{
ServerHttpRequest request = exchange.getRequest();
if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)){
return onError(exchange,"No authorization header",HttpStatus.UNAUTHORIZED);
}
String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
String jwt = authorizationHeader.replace("Bearer ", ""); //Make sure you add space
if (!isJwtValid(jwt)){
return onError(exchange, "Jwt token is invalid",HttpStatus.UNAUTHORIZED);
}
return chain.filter(exchange);
};
}
private Mono<Void> onError(ServerWebExchange exchange,String err,HttpStatus httpStatus){
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(httpStatus);
return response.setComplete();
}
private boolean isJwtValid(String jwt){
System.out.println("1");
boolean isValid = false;
String subject = null;
String tokenSecret = environment.getProperty("token.secret");
System.out.println("2 "+tokenSecret);
SecretKey secretKey = Keys.hmacShaKeyFor(tokenSecret.getBytes());
JwtParser jwtParser = Jwts.parser().verifyWith(secretKey).build();
try{
// Jwt<Header,Claims> parsedToken = jwtParser.parse(jwt);
subject = jwtParser.parseSignedClaims(jwt).getPayload().get("userId").toString();
System.out.println("3 "+subject);
} catch(Exception ex){
isValid = false;
System.out.println("4 "+ex.getLocalizedMessage());
}
if (subject == null || subject.isEmpty()){
isValid = false;
} else {
isValid = true;
}
System.out.println("5 ");
return isValid;
}
}
Вот application.properties
моего apigateway
spring.application.name=api-gateway
server.port=8082
eureka.client.service-url.defaultZone=http://localhost:8010/eureka
spring.cloud.gateway.routes[0].id=users-status-check
spring.cloud.gateway.routes[0].uri=lb://users-ws
spring.cloud.gateway.routes[0].predicates[0]=Path=/users-ws/users/status/check
spring.cloud.gateway.routes[0].predicates[1]=Method=GET
spring.cloud.gateway.routes[0].predicates[2]=Header=Authorization, Bearer (.*)
spring.cloud.gateway.routes[0].filters[0]=RemoveRequestHeader=Cookie
spring.cloud.gateway.routes[0].filters[1]=RewritePath=/users-ws/(?<segment>.*), /$\{segment}
spring.cloud.gateway.routes[0].filters[2]=AuthorizationHeaderFilter
spring.cloud.gateway.routes[1].id=users-ws
spring.cloud.gateway.routes[1].uri=lb://users-ws
spring.cloud.gateway.routes[1].predicates[0]=Path=/users-ws/users
spring.cloud.gateway.routes[1].predicates[1]=Method=POST
spring.cloud.gateway.routes[1].filters[0]=RemoveRequestHeader=Cookie
spring.cloud.gateway.routes[1].filters[1]=RewritePath=/users-ws/(?<segment>.*), /$\{segment}
spring.cloud.gateway.routes[2].id=users-ws-h2-console
spring.cloud.gateway.routes[2].uri=lb://users-ws
spring.cloud.gateway.routes[2].predicates[0]=Path=/users-ws/h2-console
spring.cloud.gateway.routes[2].predicates[1]=Method=GET
spring.cloud.gateway.routes[2].filters[0]=RemoveRequestHeader=Cookie
spring.cloud.gateway.routes[2].filters[1]=RewritePath=/users-ws/(?<segment>.*), /$\{segment}
spring.cloud.gateway.routes[3].id=users-ws-login
spring.cloud.gateway.routes[3].uri=lb://users-ws
spring.cloud.gateway.routes[3].predicates[0]=Path=/users-ws/users/login
spring.cloud.gateway.routes[3].predicates[1]=Method=POST
spring.cloud.gateway.routes[3].filters[0]=RemoveRequestHeader=Cookie
spring.cloud.gateway.routes[3].filters[1]=RewritePath=/users-ws/(?<segment>.*), /$\{segment}
spring.cloud.gateway.routes[4].id=users-ws-get-update-delete
spring.cloud.gateway.routes[4].uri=lb://users-ws
spring.cloud.gateway.routes[4].predicates[0]=Path=/users-ws/users/**
spring.cloud.gateway.routes[4].predicates[1]=Method=GET,PUT,DELETE
spring.cloud.gateway.routes[4].predicates[2]=Header=Authorization, Bearer (.*)
spring.cloud.gateway.routes[4].filters[0]=RemoveRequestHeader=Cookie
spring.cloud.gateway.routes[4].filters[1]=AuthorizationHeaderFilter
spring.cloud.gateway.routes[4].filters[2]=RewritePath=/users-ws/(?<segment>.*), /$\{segment}
token.secret=1aBcD3eF4gH5iJ6kL7mN8oP9qRsTuVwXyZ0A1bCdEfG2hI3jK4lM5nO6pQ7rStU8vW9xYz
@wxker это моя вкладка авторизации firebasestorage.googleapis.com/v0/b/myproject-6952a.appspot.com/…
Можете ли вы включить журналы безопасности Spring в микросервисах ваших пользователей, добавив в свой application.properties (или аналогичный) logging.logger.org.springframework.security=DEBUG. Вы должны увидеть, откуда взялся код 403.
@silver_mx logging.logger.org.springframework.security=DEBUG не является допустимым свойством
См. baeldung.com/spring-security-enable-logging . Да, я неправильно указал объект недвижимости, извините.
@silver_mx Я получаю эти журналы o.s.security.web.FilterChainProxy: защита GET /users/status/check o.s.s.w.a.AnonymousAuthenticationFilter: установите для SecurityContextHolder анонимный SecurityContext o.s.s.w.a.Http403ForbiddenEntryPoint: вызывается точка входа с предварительной аутентификацией. Отказ в доступе o.s.security.web.FilterChainProxy: защита GET/error o.s.s.w.a.AnonymousAuthenticationFilter: установите SecurityContextHolder в анонимный SecurityContext o.s.s.w.a.Http403ForbiddenEntryPoint: вызывается точка входа с предварительной аутентификацией. Отказ в доступе
Я думаю, что в вашей службе пользователей есть какая-то конфигурация безопасности, но ваша ссылка на исходный код не работает. Проблема, вероятно, заключается в том, как настроена безопасность Spring. Можете ли вы исправить ссылку, чтобы увидеть полный исходный код?
@silver_mx Можете ли вы проверить эту ссылку github.com/BraveEvidence/SpringBottMicorServiceTry для получения исходного кода
При добавлении получается = MediaType.TEXT_PLAIN_VALUE.
@GetMapping(path = "/status/check", produces = MediaType.TEXT_PLAIN_VALUE)
public String status()
{
System.out.println("hereeeeeeeeeee");
return "Working";
}
не работает та же проблема. Кроме того, URL-адрес, по которому вы нажимаете, неправильный. Это должен быть localhost:8082/users-ws/users/status/check и для этого требуется токен носителя, чтобы вы не могли использовать его из браузера, поскольку я добавил AuthorisationFilter к этой конечной точке.
В WebSecurity
ваш первый requestMatchers
проверяет безопасность только для /users
и /h2-console/**
, поэтому ваша конечная точка /users/status/checks
никогда не будет авторизована каким-либо фильтром и всегда будет возвращать 403.
Ваша конечная точка POST /users
всегда разрешена, поэтому она у вас работает.
Я обновил файл WebSecurity.java
в вашей службе пользователей и изменил строку:
.authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.POST, "/users")
.permitAll()
к
.authorizeHttpRequests(auth -> auth.requestMatchers("/users/**")
.permitAll()
Таким образом, Spring Security разрешает не только запросы POST
, но и запросы GET
, а также вы можете вызывать пути под /users
. После этого я получил правильный ответ.
На снимке экрана почтальона вы устанавливаете авторизацию вручную на вкладке «Заголовки». Просто для проверки работоспособности, установлено ли что-нибудь на вкладке «Авторизация»?