我使用的是 jobrunr-spring-boot-3-starter,版本 7.0.0-RC.1,并设置了 PostgreSQL 数据库 - JobRunr 将其选为默认存储提供程序。
现在,我添加了 Redis 集成(通过 Lettuce),并且 JobRunr 已开始将其选为默认存储,但我不希望这样做。
我还没有对 JobRunr 应用任何自定义配置。强制 JobRunr 坚持使用 PostgreSQL 数据源的最佳方法是什么?
我使用的是 jobrunr-spring-boot-3-starter,版本 7.0.0-RC.1,并设置了 PostgreSQL 数据库 - JobRunr 将其选为默认存储提供程序。
现在,我添加了 Redis 集成(通过 Lettuce),并且 JobRunr 已开始将其选为默认存储,但我不希望这样做。
我还没有对 JobRunr 应用任何自定义配置。强制 JobRunr 坚持使用 PostgreSQL 数据源的最佳方法是什么?
我在 docker-compose 中使用以下配置部署了 3 节点 kafka 集群
卡夫卡集群:
services:
kafka1:
image: confluentinc/cp-kafka:latest
hostname: kafka1
container_name: kafka1
ports:
- "9092:9092"
environment:
CLUSTER_ID: "7bes6xCzSMeUR-RRas3gMQ"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT'
KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://kafka1:29092,PLAINTEXT_HOST://localhost:9092'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 5000
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9997
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka1 -Dcom.sun.management.jmxremote.rmi.port=9997'
KAFKA_PROCESS_ROLES: 'broker,controller'
KAFKA_NODE_ID: 1
KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka1:29093,2@kafka2:29093,3@kafka3:29093'
KAFKA_LISTENERS: 'PLAINTEXT://kafka1:29092,CONTROLLER://kafka1:29093,,PLAINTEXT_HOST://0.0.0.0:9092'
KAFKA_INTER_BROKER_LISTENER_NAME: 'PLAINTEXT'
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
volumes:
- kafka1-data:/var/lib/kafka/data
- ./scripts/update_run.sh:/tmp/update_run.sh
command: "bash -c 'if [ ! -f /tmp/update_run.sh ]; then echo \"ERROR: Did you forget the update_run.sh file that came with this docker-compose.yml file?\" && exit 1 ; else /tmp/update_run.sh && /etc/confluent/docker/run ; fi'"
kafka2:
image: confluentinc/cp-kafka:latest
hostname: kafka2
container_name: kafka2
ports:
- "9093:9092"
environment:
CLUSTER_ID: "7bes6xCzSMeUR-RRas3gMQ"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT'
KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://kafka2:29092,PLAINTEXT_HOST://localhost:9093'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 5000
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9997
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka2 -Dcom.sun.management.jmxremote.rmi.port=9998'
KAFKA_PROCESS_ROLES: 'broker,controller'
KAFKA_NODE_ID: 2
KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka1:29093,2@kafka2:29093,3@kafka3:29093'
KAFKA_LISTENERS: 'PLAINTEXT://kafka2:29092,CONTROLLER://kafka2:29093,PLAINTEXT_HOST://0.0.0.0:9093'
KAFKA_INTER_BROKER_LISTENER_NAME: 'PLAINTEXT'
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
volumes:
- kafka2-data:/var/lib/kafka/data
- ./scripts/update_run.sh:/tmp/update_run.sh
command: "bash -c 'if [ ! -f /tmp/update_run.sh ]; then echo \"ERROR: Did you forget the update_run.sh file that came with this docker-compose.yml file?\" && exit 1 ; else /tmp/update_run.sh && /etc/confluent/docker/run ; fi'"
kafka3:
image: confluentinc/cp-kafka:latest
hostname: kafka3
container_name: kafka3
ports:
- "9094:9092"
environment:
CLUSTER_ID: "7bes6xCzSMeUR-RRas3gMQ"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT'
KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://kafka3:29092,PLAINTEXT_HOST://localhost:9094'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 5000
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9997
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka3 -Dcom.sun.management.jmxremote.rmi.port=9999'
KAFKA_PROCESS_ROLES: 'broker,controller'
KAFKA_NODE_ID: 3
KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka1:29093,2@kafka2:29093,3@kafka3:29093'
KAFKA_LISTENERS: 'PLAINTEXT://kafka3:29092,CONTROLLER://kafka3:29093,PLAINTEXT_HOST://0.0.0.0:9094'
KAFKA_INTER_BROKER_LISTENER_NAME: 'PLAINTEXT'
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
volumes:
- kafka3-data:/var/lib/kafka/data
- ./scripts/update_run.sh:/tmp/update_run.sh
command: "bash -c 'if [ ! -f /tmp/update_run.sh ]; then echo \"ERROR: Did you forget the update_run.sh file that came with this docker-compose.yml file?\" && exit 1 ; else /tmp/update_run.sh && /etc/confluent/docker/run ; fi'"
我的 Spring Boot 应用程序无法维持连接并生成以下日志
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-2, groupId=transaction-group] Discovered group coordinator localhost:9093 (id: 2147483645 rack: null)
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-1, groupId=transaction-group] Discovered group coordinator localhost:9093 (id: 2147483645 rack: null)
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-2, groupId=transaction-group] Group coordinator localhost:9093 (id: 2147483645 rack: null) is unavailable or invalid due to cause: coordinator unavailable. isDisconnected: false. Rediscovery will be attempted.
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-1, groupId=transaction-group] Group coordinator localhost:9093 (id: 2147483645 rack: null) is unavailable or invalid due to cause: coordinator unavailable. isDisconnected: false. Rediscovery will be attempted.
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-2, groupId=transaction-group] Requesting disconnect from last known coordinator localhost:9093 (id: 2147483645 rack: null)
2024-03-29T20:00:23.440-06:00 [Consumer clientId=consumer-transaction-group-1, groupId=transaction-group] Requesting disconnect from last known coordinator localhost:9093 (id: 2147483645 rack: null)
2024-03-29T20:00:23.547-06:00 [Consumer clientId=consumer-transaction-group-2, groupId=transaction-group] Discovered group coordinator localhost:9093 (id: 2147483645 rack: null)
这是我的应用程序中的卡夫卡属性。
kafka:
bootstrap-servers: localhost:9092,localhost:9093,localhost:9094
listener:
ack-mode: manual
properties:
schema.registry.url: http://localhost:8185/
consumer:
group-id: transaction-group
enable-auto-commit: false
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: io.confluent.kafka.serializers.protobuf.KafkaProtobufDeserializer
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer
transaction-id-prefix: tx-
properties:
enable-idempotence: true
是什么原因导致连接断开?当我部署单节点 kafka 集群时,这个问题就消失了。
我们可以使用以下curl命令将包含压缩LDIF文件的ZIP文件上传到小型Spring Boot应用程序:
curl -k -X POST -F“file=@/dev/Cservice.zip;type=application/zip” https://sag01.xxaws.com:10006/Cservice --cert /dev/axis.pem --key /gx/dev/axis.key
Spring Boot 应用程序接收 ZIPPED LDIF 文件,将其解压缩,然后根据解压缩的 LDIF 文件中的行进行一些处理。
但在某些环境中,他们没有Linux,因此无法使用Curl,所以我现在尝试实现一个powershell脚本来执行与curl命令相同的上传,并且我发现这个线程较旧的Stackoverflow线程(Powershell无法使用多部分表单数据将超过 ~50MB 的 zip 文件上传到 REST API),同时搜索如何实现这一目标。
我一直在尝试使用“Ralph”在较早的 SO 线程中发布的第一个 powershell 脚本,在Powershell 无法使用 Multipart form-data to REST API 上传超过 ~50MB 的 zip 文件),但针对我们的环境进行了修改(主要区别在于我们使用证书身份验证)_
这是我目前在 powershell 上的尝试:
# From: https://stackoverflow.com/questions/69038508/powershell-is-unable-to-upload-zip-file-over-50mb-using-multipart-form-data-to
Write-output "RUNNING: 8from-stackoverflow.ps1"
$Uri = 'https://sag01.gxaws.com:10006/CService'
$fileBytes = [System.IO.File]::ReadAllBytes("G:\Dev\CService.zip");
$enc = [System.Text.Encoding]::GetEncoding('utf-8')
$fileEnc = $enc.GetString($fileBytes)
Invoke-WebRequest -Uri $Uri -method POST -TimeoutSec 999999 -Certificate (Get-PfxCertificate axisWithKey.pfx) -SkipCertificateCheck `
-Headers @{ "accept"="*/*"} `
-ContentType "multipart/form-data; boundary=WebKitFormBoundaryT2XycANuthCIUwGk" `
-Body ([System.Text.Encoding]::UTF8.GetBytes("--WebKitFormBoundaryT2XycANuthCIUwGk$([char]13)$([char]10)Content-Disposition: form-data; name=`"file`"; filename=`"CService.zip`"$([char]13)$([char]10)Content-Type: application/x-zip-compressed$([char]13)$([char]10)$([char]13)$([char]10))$fileEnc($([char]13)$([char]10)-- WebKitFormBoundaryT2XycANuthCIUwGk--$([char]13)$([char]10)"))
当我运行上面的 powershell 脚本时,我跟踪正在接收上传的应用程序日志,看起来 powershell 脚本正在尝试上传“CService.zip”文件,并且 spring boot 应用程序正在看到上传请求,我可以看到似乎是 zip 文件的二进制数据。这是 powershell 脚本运行时 ZIP 文件日志记录的开始(我希望出现下面的行):
--WebKitFormBoundaryT2XycANuthCIUwGk
Content-Disposition: form-data; name="file"; filename="CService.zip"
Content-Type: application/x-zip-compressed
�*T*�d~��tb����Z▒¿½n�no4�lÏ¢S���y~t�y�r�a��ï¿m?m�í������l�_���^^���y����
然而,在应用程序收到 ZIP 文件后,它应该解压缩内容,然后记录行,但它似乎无法做到这一点:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.u.StringUtils [https-jsse-nio-8888-exec-2] LDIF before reMap method:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.u.StringUtils [https-jsse-nio-8888-exec-2] LDIF after reMap method:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.s.LDAPService [https-jsse-nio-8888-exec-2] Lidf entries count = 0
当我运行工作的 Curl 命令时,我查看了相同的服务器端应用程序日志记录,并且它输出二进制数据的日志记录看起来与我运行 powershell 脚本时的日志记录完全不同。
以下是运行 curl 时的日志记录片段:
2024-03-14 18:38:50,916 DEBUG o.a.j.l.DirectJDKLog [https-jsse-nio-8888-exec-9] Received [--------------------------a18e445ef02489d2^M
Content-Disposition: form-data; name="file"; filename="CService.zip"^M
Content-Type: application/zip^M
^M
PK^C^D^T^@^@^@^H^@QmuVe^XÂ<86>(^O^@^@'~^B^@^S^@^@^@CService.ldif<9a>]kT ^VEß^Cù^Où^A*u¿êC^P&¦¡q µiõa<9e><86>2Vb^M±*T*Íd~ýÜtb<8e><8c>û<84>^^Z^O^[ön<90>no4®lÏ¢S¬ú¸y~tºyñrûaòå<9f>é³^?m?m<9e>í<9e><9d>ÿûr^?^Z<8f><9f>l¯_üºÚ^^¬<9e>¼yÿâõÏÇ·ÿúiûÓ<93>7/Þ?{ûìèçíï«Ýæój³^?ròâýÛÃ<83
另外,我注意到运行 powershell 时的内容长度大约是运行 Curl 时的长度的两倍。
所以我认为我一定是对 powershell 脚本中编码 ZIP 文件的部分做错了什么?或者,Curl 上传到 Spring Boot 应用程序可能有效,因为 Curl 正在执行不同类型的编码或其他操作?
我希望这里有人能够提供帮助,因为我已经尝试让它工作几天了,而且我觉得我离解决方案越来越远,而不是更接近,所以我决定尝试在这里发帖。
如果有任何问题,请告诉我,我会尽力回答!
提前致谢,吉姆
编辑:这是根据 mklement0 的建议最终起作用的(在评论中):
#FROM: https://stackoverflow.com/questions/78162873/problem-trying-to-use-powershell-to-upload-a-zip-file-to-a-spring-boot-applicati
#and:
#FROM: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.4#example-5-submit-a-multipart-form-data-file
$FilePath = 'G:\Dev\CService.zip'
$URL = 'https://sag02.xxaws.com:10006/CService'
Write-output "ZIP File: $FilePath"
Write-output "URL: $URL"
$FieldName = 'file'
$ContentType = 'application/zip'
$FileStream = [System.IO.FileStream]::new($filePath, [System.IO.FileMode]::Open)
$FileHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new('form-data')
$FileHeader.Name = $FieldName
$FileHeader.FileName = Split-Path -leaf $FilePath
$FileContent = [System.Net.Http.StreamContent]::new($FileStream)
$FileContent.Headers.ContentDisposition = $FileHeader
$FileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse($ContentType)
$MultipartContent = [System.Net.Http.MultipartFormDataContent]::new()
$MultipartContent.Add($FileContent)
$Response = Invoke-WebRequest -Body $MultipartContent -Method POST -Uri $URL -TimeoutSec 999999 -Certificate (Get-PfxCertificate geoaxisWithKey.pfx) -SkipCertificateCheck
Write-output $Response
我创建了一个 spring-boot 项目并定义了一个带有 1 个端点的 REST 控制器/employers
@RestController
public class EmployerController {
@Autowired
private EmployerService employerService;
@GetMapping(path = "/employers")
public List<Employer> getEmployers() {
return (List<Employer>) employerService.getEmployers();
}
}
此外,我还创建了关联的 EmployerService、EmployerRepository 和 Employer 实体
当我将 Swagger/OpenAPI 添加到类路径,然后导航到 时http://localhost:8080/swagger-ui.html
,雇主实体有一个完整的 CRUD REST 定义,其中包括GET/POST/PUT/DELETE/PATCH
当我只定义了一个端点时,为什么要为雇主定义完整的 CRUD REST API GET /employers
?如果这是可配置的,是否可以禁用 REST API 的自动创建?
我有一个用户实体,其审核字段名为lastUpdatedUserId
(与 相同LastModifiedBy
)。这是一个整数字段。我正在尝试使用 Spring 提供的审核功能并执行文档中所述的所有操作。当我尝试重写getCurrentAuditor
的方法时AuditorAware
,如果我硬编码一个整数作为返回值,它就可以正常工作。如果我尝试使用UserRepository
(Spring Data JPA 存储库)获取已登录用户的用户 ID,则会收到错误Could not commit JPA transaction
。我正在使用 Gmail Oauth2 进行身份验证。堆栈跟踪太长,我无法在这里发布。我尝试调试,但这并不容易。
如果有人知道原因,请告诉我。
@EntityListeners(AuditingEntityListener.class)
public class User {
@LastModifiedBy
@Column(name = "lst_updtd_usr_id")
private Integer lastUpdatedUserId;
...
}
public class AuditorAwareImpl implements AuditorAware<Integer> {
@Autowired
private UserRepository userRepo;
@Override
public Optional<Integer> getCurrentAuditor() {
// your custom logic
DefaultOidcUser oidcUser = (DefaultOidcUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String emailId = oidcUser.getEmail();
User user = userRepo.findByEmailId(emailId);
return Optional.of(user.getUserId());
}
}
@Configuration
@EnableJpaAuditing(auditorAwareRef="auditorP")
public class PersistenceConfig {
@Bean
AuditorAware<Integer> auditorP() {
return new AuditorAwareImpl();
}
}
我用 Spring Cloud Streaming 做了一些实验,其中 kafka 是数据源。需要配置dlq
,但我的配置不支持它。所以我打开了开源示例,它确实有效。
spring.cloud.stream.kafka.streams.binder:
configuration:
commit.interval.ms: 1000
default.key.serde: org.apache.kafka.common.serialization.Serdes$StringSerde
default.value.serde: org.apache.kafka.common.serialization.Serdes$IntegerSerde
application.id: dlq-demo-sample
serdeError: sendToDlq
spring.cloud.stream.bindings.process-out-0:
destination: counts
spring.cloud.stream.bindings.process-in-0:
destination: words
spring.cloud.stream.kafka.streams.bindings.process-in-0.consumer:
dlqName: words-count-dlq
valueSerde: org.apache.kafka.common.serialization.Serdes$IntegerSerde
该示例使用<spring-cloud.version>2020.0.2</spring-cloud.version>
和
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/>
</parent>
我将此库升级到较新的版本:<spring-cloud.version>2023.0.0</spring-cloud.version>
并且
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/>
</parent>
更新版本后,通常的场景按预期工作(如果值 serde 为StringSerde
),但 DLQ 配置被忽略(使用原始yml
)。
您认为我将示例更新为不兼容的库吗?
...以下spring 文档应该兼容:
|Release Train | Spring Boot Generation |
|---------------------------------------------|
|2023.0.x aka Leyton | 3.2.x |
...
您认为我错过了一些重要的属性以使其与较新的 Spring 版本一起使用吗?
在使用 Spring Security 时,我遇到了一个奇怪的问题,我无法解决这个问题。
如果我使用注释声明自定义身份验证提供程序@Component
,Spring 将不再能够检测BasicAuthenticationFilter
. 我使用邮递员在标头中传递基本身份验证和自定义过滤器的密钥。这是异常/错误:
2024-02-26T01:56:59.981+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Mvc [pattern='/public/**'], Filters=[]] (1/2)
2024-02-26T01:56:59.981+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@409df37d, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2ab1c7a9, org.springframework.security.web.context.SecurityContextHolderFilter@22c14d10, org.springframework.security.web.header.HeaderWriterFilter@e594c46, org.springframework.security.web.csrf.CsrfFilter@27b7913, org.springframework.security.web.authentication.logout.LogoutFilter@411e567e, com.prajwal.security.config.filter.CustomFilter@7cfb4736, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@5257123d, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@38276668, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3344c1d7, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6e818345, org.springframework.security.web.access.ExceptionTranslationFilter@5dd5422f, org.springframework.security.web.access.intercept.AuthorizationFilter@339b45f8]] (2/2)
2024-02-26T01:56:59.981+05:30 DEBUG 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Securing GET /private/hello
2024-02-26T01:56:59.981+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking DisableEncodeUrlFilter (1/13)
2024-02-26T01:56:59.981+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (2/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderFilter (3/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking HeaderWriterFilter (4/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking CsrfFilter (5/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.csrf.CsrfFilter : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (6/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern='/logout', POST]
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking CustomFilter (7/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy : Invoking BasicAuthenticationFilter (8/13)
2024-02-26T01:56:59.982+05:30 TRACE 4304 --- [nio-8080-exec-4] o.s.s.w.a.www.BasicAuthenticationFilter : Found username 'prajwal' in Basic Authorization header
2024-02-26T01:56:59.982+05:30 DEBUG 4304 --- [nio-8080-exec-4] o.s.s.w.a.www.BasicAuthenticationFilter : Failed to process authentication request
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:234) ~[spring-security-core-6.1.5.jar:6.1.5]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:174) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at com.prajwal.security.config.filter.CustomFilter.doFilterInternal(CustomFilter.java:34) ~[classes/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191) ~[spring-security-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) ~[spring-web-6.0.14.jar:6.0.14]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.14.jar:6.0.14]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.14.jar:6.0.14]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.16.jar:10.1.16]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
自定义身份验证.java
@AllArgsConstructor
@Getter
@Setter
public class CustomAuthentication implements Authentication {
private final boolean isAuthenticated;
private final String key;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(() -> "USER");
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return null;
}
@Override
public boolean isAuthenticated() {
return this.isAuthenticated;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { }
@Override
public boolean equals(Object another) {
return false;
}
@Override
public String getName() {
return "CustomAuthentication";
}
@Override
public boolean implies(Subject subject) {
return Authentication.super.implies(subject);
}
}
CustomAuthenticationProvider.java
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Value("${our.key}")
private String key;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
CustomAuthentication ca = (CustomAuthentication) authentication;
String headerKey = ca.getKey();
if(null != headerKey && headerKey.equals(key)) {
return new CustomAuthentication(true, null);
}
return authentication;
}
@Override
public boolean supports(Class<?> authentication) {
return CustomAuthentication.class.isAssignableFrom(authentication);
}
}
自定义身份验证管理器.java
@Component
@AllArgsConstructor
public class CustomAuthenticationManager implements AuthenticationManager {
private final CustomAuthenticationProvider cap;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(cap.supports(authentication.getClass())) {
return cap.authenticate(authentication);
}
return authentication;
}
}
自定义过滤器.java
@Component
@AllArgsConstructor
public class CustomFilter extends OncePerRequestFilter {
private final CustomAuthenticationManager cam;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CustomAuthentication ca = new CustomAuthentication(false, request.getHeader("key"));
Authentication authentication = cam.authenticate(ca);
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authentication);
SecurityContextHolder.setContext(securityContext);
filterChain.doFilter(request, response);
return;
}
}
WebSecurityConfig.java
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig {
private final CustomFilter customFilter;
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers("/public/**");
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorizeConfig -> {
authorizeConfig.anyRequest().authenticated();
})
.httpBasic(Customizer.withDefaults())
.addFilterBefore(customFilter, BasicAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
JpaUserDetailsService.java
@AllArgsConstructor
@Service
public class JpaUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
System.out.println("UserDetailsService is called");
User user = userRepository.findByName(username);
System.out.println("User: " + user.getUsername() + " accessed the pages");
return new SecurityUser(user);
}
}
我已经安静地从事 Spring 项目一段时间了,在处理数据库时我几乎从来不需要添加 @Transactional 注释。但我已经掌握了如何在 Spring Boot 中管理事务的理论知识。我现在想知道当不添加 @Transactional 和处理数据库的方法时我是否做错了。
我正在开发一个电子商务网站,并且仅当 url 与 /auth/login 不匹配时,我才想有条件地在布局中显示 div。
<div sec:authorize="isAnonymous()" th:if="${!/auth/login}">
<a th:href="@{/auth/login}">Login</a>
<a th:href="@{/auth/register}">Register</a>
</div>
我阅读了文档,但我所能找到的只是 params 对象的信息。我还在 google 上看到了一些关于 #httpservlet 对象的内容,但是我确实认为这是贬值的,因为我没有在 intellij 中获得自动完成功能。
我正在积累有关 Spring Boot 的知识。
到目前为止我已经创建了:
我现在想尝试使用从正文获取 ID 的发布请求(这是为了学习而不是最佳实践,因为我知道这将在路径中使用它)。
但是,我的代码不断返回“0”而不是 ID...
我究竟做错了什么?
@RestController
public class spannerController {
@Autowired
CdRequestService cdRequestService;
@GetMapping("/getData")
public Optional<Request> getData() {
Optional<Request> request;
request = requestService.getRequest(101);
return request;
}
@GetMapping("/getData/{id}")
public Optional<Request> getData(@PathVariable("id") int id) {
Optional<Request> request;
request = requestService.getRequest(id);
return request;
}
@PostMapping(value = "/getData",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public void getDataPost(@RequestBody PostRequest request) {
System.out.println(request);
System.out.println(request.getId());
}
}
public class PostRequest {
int id;
public PostRequest() {
}
public PostRequest(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}