端口8080与端口8180重叠
这是我第一次使用keycloack、spring Boot 和docker启动一个应用程序。设置和使用keycloack本身并没有引起任何问题。Docker运行得很顺利。但是当我请求从postman到spring方法时,我得到一个错误错误错误:connect EASPING REFUSED 127.0.0.1:8080
docker-compose.yml
version: '3.9'
services:
keycloak:
container_name: keycloak-auth
image: quay.io/keycloak/keycloak:22.0.1
command:
- "start-dev"
ports:
- "8180:8080"
networks:
- keycloak
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: password
KC_DB: postgres
KC_DB_URL_HOST: keycloak-db
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: password
KC_HEALTH_ENABLED: true
depends_on:
- keycloak-db
keycloak-db:
image: postgres:14-alpine
container_name: keycloak-db
ports:
- "5433:5432"
volumes:
- postgres_data_keycloak:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
networks: [ keycloak ]
healthcheck:
test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U" ]
timeout: 45s
interval: 10s
retries: 10
activemq:
image: webcenter/activemq:latest
ports:
# mqtt
- "1883:1883"
# amqp
- "5672:5672"
# ui
- "8161:8161"
# stomp
- "61613:61613"
# ws
- "61614:61614"
# jms
- "61616:61616"
networks: [ activemq ]
volumes: [ "activemq-data:/opt/activemq/conf", "activemq-data:/data/activemq", "activemq-data:/var/log/activemq" ]
environment:
ACTIVEMQ_REMOVE_DEFAULT_ACCOUNT: "true"
ACTIVEMQ_ADMIN_LOGIN: admin
ACTIVEMQ_ADMIN_PASSWORD: password
ACTIVEMQ_WRITE_LOGIN: write
ACTIVEMQ_WRITE_PASSWORD: password
ACTIVEMQ_READ_LOGIN: read
ACTIVEMQ_READ_PASSWORD: password
ACTIVEMQ_JMX_LOGIN: jmx
ACTIVEMQ_JMX_PASSWORD: password
ACTIVEMQ_STATIC_TOPICS: static-topic-1;static-topic-2;autoTopic
ACTIVEMQ_STATIC_QUEUES: static-queue-1;static-queue-2
ACTIVEMQ_ENABLED_SCHEDULER: "true"
ACTIVEMQ_MIN_MEMORY: 512
ACTIVEMQ_MAX_MEMORY: 2048
networks:
keycloak:
name: keycloak
driver: bridge
activemq: { }
volumes:
postgres_data_keycloak:
driver: local
activemq-data:
driver: local
字符串
安全配置
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
//TODO: security without @PreAuthorize
/* .authorizeHttpRequests(registry -> registry
.requestMatchers(HttpMethod.GET, "/api/**").hasRole("USER")
.requestMatchers(HttpMethod.POST, "/api/**").hasRole("PERSON")
.anyRequest().authenticated()
)*/
.oauth2ResourceServer(oauth2Configurer -> oauth2Configurer
.jwt(jwtConfigurer -> jwtConfigurer
.jwtAuthenticationConverter(jwt -> {
Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
Collection<String> roles = realmAccess.get("roles");
var grantedAuthorities = roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
return new JwtAuthenticationToken(jwt, grantedAuthorities);
})));
return httpSecurity.build();
}
}
型
控制器
@RestController
@RequestMapping(value = "/api", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
@Slf4j
public class AutomobileRestController implements AutomobileResource, AutomobileOpenApi, JMSPublisher {
private final AutomobileRepository repository;
private final JmsTemplate jmsTemplate;
public static double getTiming(Instant start, Instant end) {
return Duration.between(start, end).toMillis();
}
@Transactional
@PostConstruct
public void init() {
repository.save(new Automobile(1L, "Ford", "Green", LocalDateTime.now(), LocalDateTime.now(), true, false));
}
@PostMapping("/automobiles")
@ResponseStatus(HttpStatus.CREATED)
@PreAuthorize("hasRole('ADMIN')")
//@RolesAllowed("ADMIN")
public Automobile saveAutomobile(@Valid @RequestBody Automobile automobile) {
log.info("saveAutomobile() - start: automobile = {}", automobile);
Automobile savedAutomobile = repository.save(automobile);
log.info("saveAutomobile() - end: savedAutomobile = {}", savedAutomobile.getId());
return savedAutomobile;
}
@GetMapping("/automobiles")
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('USER')")
public Collection<Automobile> getAllAutomobiles() {
log.info("getAllAutomobiles() - start");
Collection<Automobile> collection = repository.findAll();
log.info("getAllAutomobiles() - end");
return collection;
}
@GetMapping("/automobiles/{id}")
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('PERSON')")
public Automobile getAutomobileById(@PathVariable Long id) {
log.info("getAutomobileById() - start: id = {}", id);
Automobile receivedAutomobile = repository.findById(id)
.orElseThrow(ThereIsNoSuchAutoException::new);
if (receivedAutomobile.getDeleted()) {
throw new AutoWasDeletedException();
}
log.info("getAutomobileById() - end: Automobile = {}", receivedAutomobile.getId());
return receivedAutomobile;
}
@Hidden
@GetMapping(value = "/automobiles", params = {"name"})
@ResponseStatus(HttpStatus.OK)
public Collection<Automobile> findAutomobileByName(@RequestParam(value = "name") String name) {
log.info("findAutomobileByName() - start: name = {}", name);
Collection<Automobile> collection = repository.findByName(name);
log.info("findAutomobileByName() - end: collection = {}", collection);
return collection;
}
@PutMapping("/automobiles/{id}")
@ResponseStatus(HttpStatus.OK)
//@CachePut(value = "automobile", key = "#id")
public Automobile refreshAutomobile(@PathVariable Long id, @RequestBody Automobile automobile) {
log.info("refreshAutomobile() - start: id = {}, automobile = {}", id, automobile);
Automobile updatedAutomobile = repository.findById(id)
.map(entity -> {
entity.checkColor(automobile);
entity.setName(automobile.getName());
entity.setColor(automobile.getColor());
entity.setUpdateDate(automobile.getUpdateDate());
if (entity.getDeleted()) {
throw new AutoWasDeletedException();
}
return repository.save(entity);
})
//.orElseThrow(() -> new EntityNotFoundException("Automobile not found with id = " + id));
.orElseThrow(ThereIsNoSuchAutoException::new);
log.info("refreshAutomobile() - end: updatedAutomobile = {}", updatedAutomobile);
return updatedAutomobile;
}
@DeleteMapping("/automobiles/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
@CacheEvict(value = "automobile", key = "#id")
public String removeAutomobileById(@PathVariable Long id) {
log.info("removeAutomobileById() - start: id = {}", id);
Automobile deletedAutomobile = repository.findById(id)
.orElseThrow(ThereIsNoSuchAutoException::new);
deletedAutomobile.setDeleted(Boolean.TRUE);
repository.save(deletedAutomobile);
log.info("removeAutomobileById() - end: id = {}", id);
return "Deleted";
}
@Hidden
@DeleteMapping("/automobiles")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void removeAllAutomobiles() {
log.info("removeAllAutomobiles() - start");
repository.deleteAll();
log.info("removeAllAutomobiles() - end");
}
@GetMapping(value = "/automobiles", params = {"color"})
@ResponseStatus(HttpStatus.OK)
public Collection<Automobile> findAutomobileByColor(
@Parameter(description = "Name of the Automobile to be obtained. Cannot be empty.", required = true)
@RequestParam(value = "color") String color) {
Instant start = Instant.now();
log.info("findAutomobileByColor() - start: time = {}", start);
log.info("findAutomobileByColor() - start: color = {}", color);
Collection<Automobile> collection = repository.findByColor(color);
Instant end = Instant.now();
log.info("findAutomobileByColor() - end: milliseconds = {}", getTiming(start, end));
log.info("findAutomobileByColor() - end: collection = {}", collection);
return collection;
}
@GetMapping(value = "/automobiles", params = {"name", "color"})
@ResponseStatus(HttpStatus.OK)
public Collection<Automobile> findAutomobileByNameAndColor(
@Parameter(description = "Name of the Automobile to be obtained. Cannot be empty.", required = true)
@RequestParam(value = "name") String name, @RequestParam(value = "color") String color) {
log.info("findAutomobileByNameAndColor() - start: name = {}, color = {}", name, color);
Collection<Automobile> collection = repository.findByNameAndColor(name, color);
log.info("findAutomobileByNameAndColor() - end: collection = {}", collection);
return collection;
}
@GetMapping(value = "/automobiles", params = {"colorStartsWith"})
@ResponseStatus(HttpStatus.OK)
public Collection<Automobile> findAutomobileByColorStartsWith(
@RequestParam(value = "colorStartsWith") String colorStartsWith,
@RequestParam(value = "page") int page,
@RequestParam(value = "size") int size) {
log.info("findAutomobileByColorStartsWith() - start: color = {}", colorStartsWith);
Collection<Automobile> collection = repository
.findByColorStartsWith(colorStartsWith, PageRequest.of(page, size, Sort.by("color")));
log.info("findAutomobileByColorStartsWith() - end: collection = {}", collection);
return collection;
}
@GetMapping("/automobiles-names")
@ResponseStatus(HttpStatus.OK)
public List<String> getAllAutomobilesByName() {
log.info("getAllAutomobilesByName() - start");
List<Automobile> collection = repository.findAll();
List<String> collectionName = collection.stream()
.map(Automobile::getName)
.sorted()
.collect(Collectors.toList());
log.info("getAllAutomobilesByName() - end");
return collectionName;
}
@Override
@PostMapping("/message")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<Automobile> pushMessage(@RequestBody Automobile automobile) {
try {
Topic autoTopic = Objects.requireNonNull(jmsTemplate
.getConnectionFactory()).createConnection().createSession().createTopic("AutoTopic");
Automobile savedAutomobile = repository.save(automobile);
log.info("\u001B[32m" + "Sending Automobile with id: " + savedAutomobile.getId() + "\u001B[0m");
jmsTemplate.convertAndSend(autoTopic, savedAutomobile);
return new ResponseEntity<>(savedAutomobile, HttpStatus.OK);
} catch (Exception exception) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
型
Application.yml
spring:
application:
name: App
profiles:
active: development
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/automobiles
username: postgres
password: postgres
jpa:
hibernate:
ddl-auto: update
show-sql: true
database: postgresql
database-platform: org.hibernate.dialect.PostgreSQLDialect
security:
oauth2:
resource-server:
jwt:
issuer-uri: http://localhost:8180/realms/automobile-realm
jms:
pub-sub-domain: true
activemq:
broker-url: tcp://localhost:61616
server:
port: 8080
servlet:
context-path: /demo
logging:
pattern:
console: "%d %-5level %logger : %msg%n"
level:
org.springframework: info
org.springframework.security: debug
org.springframework.security.oauth2: debug
springdoc:
swagger-ui:
path: /swagger-ui.html
api-docs:
path: /v3/api-docs.yaml
management:
endpoints:
web:
exposure:
include: "*"
型
当我发出请求时,我得到一个错误:
x1c 0d1x的数据
在keycloak本身中,以下端口设置
我检查了端口在请求过程中不是忙碌的,keycloak在端口8180上工作,也许我错过了一些设置?
Dockerfile
FROM openjdk:17
ADD /target/spring-boot-keycloak-docker-postgres.jar spring-boot-keycloak-docker-postgres.jar
ENTRYPOINT ["java", "-jar", "spring-boot-keycloak-docker-postgres.jar"]
型
docker-compose
的
logger docker-compose
1条答案
按热度按时间2ekbmq321#
问题是,你的Spring Boot 应用程序不是通过你的docker-compose文件启动的。这个文件只是启动keycloak,它是DB和活动mq服务。
您应该将Sping Boot 应用打包为Docker镜像(https://spring.io/guides/topicals/spring-boot-docker/),并将其用作Docker compose文件中的另一个服务。