Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3d9f827

Browse files
committed
feat(security): add fluent API for Security JPA
1 parentf542c6a commit3d9f827

File tree

16 files changed

+855
-15
lines changed

16 files changed

+855
-15
lines changed

‎docs/src/main/asciidoc/security-authorize-web-endpoints-reference.adoc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ The same authorization can be required with the `@PermissionsAllowed(value = { "
600600
* xref:security-authentication-mechanisms.adoc#mtls-programmatic-set-up[Set up the mutual TLS client authentication programmatically]
601601
* xref:security-cors.adoc#cors-filter-programmatic-set-up[Configuring the CORS filter programmatically]
602602
* xref:security-csrf-prevention.adoc#csrf-prevention-programmatic-set-up[Configuring the CSRF prevention programmatically]
603+
* xref:security-jpa.adoc#programmatic-set-up[Set up Basic authentication with Jakarta Persistence programmatically]
603604

604605
[[standard-security-annotations]]
605606
== Authorization using annotations

‎docs/src/main/asciidoc/security-jpa.adoc‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,31 @@ For more information about proactive authentication, see the Quarkus xref:securi
222222

223223
include::{generated-dir}/config/quarkus-security-jpa.adoc[opts=optional, leveloffset=+2]
224224

225+
[[programmatic-set-up]]
226+
== Set up Basic authentication with Jakarta Persistence programmatically
227+
228+
The `io.quarkus.vertx.http.security.HttpSecurity` CDI event allows to configure the Basic authentication mechanism programmatically.
229+
If there is more than one `IdentityProvider` handling the `io.quarkus.security.identity.request.UsernamePasswordAuthenticationRequest` request, you can configure the Basic authentication to use the Jakarta Persistence `IdentityProvider` like in the example below:
230+
231+
[source,java]
232+
----
233+
package org.acme.http.security;
234+
235+
import static io.quarkus.security.jpa.SecurityJpa.jpa;
236+
237+
import jakarta.enterprise.event.Observes;
238+
239+
import io.quarkus.vertx.http.security.HttpSecurity;
240+
241+
public class HttpSecurityConfiguration {
242+
243+
void configure(@Observes HttpSecurity httpSecurity) {
244+
httpSecurity.basic(jpa());
245+
}
246+
247+
}
248+
----
249+
225250
== References
226251

227252
* xref:security-getting-started-tutorial.adoc[Getting started with Security by using Basic authentication and Jakarta Persistence]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
packageio.quarkus.security.jpa;
2+
3+
importjava.util.Collection;
4+
5+
importio.quarkus.arc.Arc;
6+
importio.quarkus.security.identity.IdentityProvider;
7+
8+
/**
9+
* A CDI beans used to retrieve generated Quarkus Security JPA beans.
10+
*/
11+
publicinterfaceSecurityJpa {
12+
13+
/**
14+
* @return Quarkus Security JPA {@link IdentityProvider}s
15+
*/
16+
Collection<IdentityProvider<?>>getIdentityProviders();
17+
18+
/**
19+
* Looks up the {@link SecurityJpa} CDI bean and returns the Quarkus Security JPA {@link IdentityProvider}s.
20+
*
21+
* @return Quarkus Security JPA {@link IdentityProvider}s
22+
*/
23+
staticCollection<IdentityProvider<?>>jpa() {
24+
try (varsecurityJpaInstance =Arc.requireContainer().instance(SecurityJpa.class)) {
25+
returnsecurityJpaInstance.get().getIdentityProviders();
26+
}
27+
}
28+
}

‎extensions/security-jpa-reactive/deployment/src/main/java/io/quarkus/security/jpa/reactive/deployment/QuarkusSecurityJpaReactiveProcessor.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
importorg.jboss.jandex.DotName;
2727
importorg.jboss.jandex.Index;
2828

29+
importio.quarkus.arc.deployment.AdditionalBeanBuildItem;
2930
importio.quarkus.arc.deployment.GeneratedBeanBuildItem;
3031
importio.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
3132
importio.quarkus.deployment.Feature;
@@ -49,6 +50,7 @@
4950
importio.quarkus.security.jpa.common.deployment.PanacheEntityPredicateBuildItem;
5051
importio.quarkus.security.jpa.reactive.runtime.JpaReactiveIdentityProvider;
5152
importio.quarkus.security.jpa.reactive.runtime.JpaReactiveTrustedIdentityProvider;
53+
importio.quarkus.security.jpa.reactive.runtime.SecurityJpaReactiveImpl;
5254
importio.smallrye.mutiny.Uni;
5355

5456
classQuarkusSecurityJpaReactiveProcessor {
@@ -82,6 +84,11 @@ PanacheEntityPredicateBuildItem panacheEntityPredicate(List<PanacheEntityClasses
8284
returnnewPanacheEntityPredicateBuildItem(collectPanacheEntities(panacheEntityClasses));
8385
}
8486

87+
@BuildStep
88+
AdditionalBeanBuildItemregisterSecurityJpaReactiveImplCdiBean() {
89+
returnAdditionalBeanBuildItem.unremovableOf(SecurityJpaReactiveImpl.class);
90+
}
91+
8592
privatestaticSet<String>collectPanacheEntities(List<PanacheEntityClassesBuildItem>panacheEntityClassesBuildItems) {
8693
Set<String>modelClasses =newHashSet<>();
8794
for (PanacheEntityClassesBuildItempanacheEntityClasses :panacheEntityClassesBuildItems) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
packageio.quarkus.security.jpa.reactive;
2+
3+
importstaticorg.hamcrest.Matchers.containsString;
4+
importstaticorg.hamcrest.Matchers.equalTo;
5+
importstaticorg.hamcrest.Matchers.notNullValue;
6+
7+
importjava.time.Duration;
8+
9+
importjakarta.enterprise.event.Observes;
10+
11+
importorg.jboss.shrinkwrap.api.ShrinkWrap;
12+
importorg.jboss.shrinkwrap.api.asset.StringAsset;
13+
importorg.jboss.shrinkwrap.api.spec.JavaArchive;
14+
importorg.junit.jupiter.api.Test;
15+
importorg.junit.jupiter.api.extension.RegisterExtension;
16+
17+
importio.quarkus.security.jpa.SecurityJpa;
18+
importio.quarkus.test.QuarkusUnitTest;
19+
importio.quarkus.vertx.http.security.Form;
20+
importio.quarkus.vertx.http.security.HttpSecurity;
21+
importio.restassured.RestAssured;
22+
importio.restassured.filter.cookie.CookieFilter;
23+
24+
publicclassSecurityJpaReactiveFluentApiTest {
25+
26+
@RegisterExtension
27+
staticQuarkusUnitTesttest =newQuarkusUnitTest().setArchiveProducer(() ->ShrinkWrap
28+
.create(JavaArchive.class)
29+
.addClasses(TestApplication.class,MinimalUserEntity.class,SecurityJpaConfiguration.class,
30+
SingleRoleSecuredResource.class)
31+
.addAsResource("minimal-config/import.sql","import.sql")
32+
.addAsResource(newStringAsset("""
33+
quarkus.datasource.db-kind=postgresql
34+
quarkus.datasource.username=${postgres.reactive.username}
35+
quarkus.datasource.password=${postgres.reactive.password}
36+
quarkus.datasource.reactive=true
37+
quarkus.datasource.reactive.url=${postgres.reactive.url}
38+
quarkus.hibernate-orm.sql-load-script=import.sql
39+
quarkus.hibernate-orm.schema-management.strategy=drop-and-create
40+
"""),"application.properties"));
41+
42+
@Test
43+
voidtestFormBasedAuthentication() {
44+
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
45+
CookieFiltercookies =newCookieFilter();
46+
RestAssured
47+
.given()
48+
.filter(cookies)
49+
.redirects().follow(false)
50+
.when()
51+
.get("/jaxrs-secured/user-secured")
52+
.then()
53+
.assertThat()
54+
.statusCode(302)
55+
.header("location",containsString("/login"))
56+
.cookie("quarkus-redirect-location",containsString("/user-secured"));
57+
58+
// test with a non-existent user
59+
RestAssured
60+
.given()
61+
.filter(cookies)
62+
.redirects().follow(false)
63+
.when()
64+
.formParam("j_username","dummy")
65+
.formParam("j_password","dummy")
66+
.post("/j_security_check")
67+
.then()
68+
.assertThat()
69+
.statusCode(302);
70+
71+
RestAssured
72+
.given()
73+
.filter(cookies)
74+
.redirects().follow(false)
75+
.when()
76+
.formParam("j_username","user")
77+
.formParam("j_password","user")
78+
.post("/j_security_check")
79+
.then()
80+
.assertThat()
81+
.statusCode(302)
82+
.header("location",containsString("/user-secured"))
83+
.cookie("laitnederc-sukrauq",notNullValue());
84+
85+
RestAssured
86+
.given()
87+
.filter(cookies)
88+
.redirects().follow(false)
89+
.when()
90+
.get("/jaxrs-secured/user-secured")
91+
.then()
92+
.assertThat()
93+
.statusCode(200)
94+
.body(equalTo("A secured message"));
95+
}
96+
97+
@Test
98+
voidtestBasicAuthentication() {
99+
RestAssured
100+
.given()
101+
.auth().preemptive().basic("user","wrong-password")
102+
.get("/jaxrs-secured/user-secured")
103+
.then()
104+
.statusCode(401);
105+
RestAssured
106+
.given()
107+
.auth().preemptive().basic("user","user")
108+
.get("/jaxrs-secured/user-secured")
109+
.then()
110+
.statusCode(200)
111+
.body(equalTo("A secured message"));
112+
}
113+
114+
publicstaticclassSecurityJpaConfiguration {
115+
116+
voidconfigure(@ObservesHttpSecurityhttpSecurity) {
117+
varform =Form.builder()
118+
.loginPage("login")
119+
.errorPage("error")
120+
.landingPage("landing")
121+
.cookieName("laitnederc-sukrauq")
122+
.newCookieInterval(Duration.ofSeconds(5))
123+
.timeout(Duration.ofSeconds(5))
124+
.encryptionKey("CHANGEIT-CHANGEIT-CHANGEIT-CHANGEIT-CHANGEIT")
125+
.build();
126+
varjpa =SecurityJpa.jpa();
127+
httpSecurity.mechanism(form,jpa).basic(jpa);
128+
}
129+
130+
}
131+
132+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
packageio.quarkus.security.jpa.reactive.runtime;
2+
3+
importjava.util.ArrayList;
4+
importjava.util.Collection;
5+
importjava.util.Collections;
6+
7+
importjakarta.enterprise.inject.Instance;
8+
importjakarta.inject.Inject;
9+
10+
importio.quarkus.security.identity.IdentityProvider;
11+
importio.quarkus.security.jpa.SecurityJpa;
12+
13+
publicfinalclassSecurityJpaReactiveImplimplementsSecurityJpa {
14+
15+
@Inject
16+
Instance<JpaReactiveIdentityProvider>jpaReactiveIdentityProvider;
17+
18+
@Inject
19+
Instance<JpaReactiveTrustedIdentityProvider>jpaReactiveTrustedIdentityProvider;
20+
21+
@Override
22+
publicCollection<IdentityProvider<?>>getIdentityProviders() {
23+
finalCollection<IdentityProvider<?>>result =newArrayList<>();
24+
if (jpaReactiveIdentityProvider.isResolvable()) {
25+
result.add(jpaReactiveIdentityProvider.get());
26+
}
27+
if (jpaReactiveTrustedIdentityProvider.isResolvable()) {
28+
result.add(jpaReactiveTrustedIdentityProvider.get());
29+
}
30+
returnCollections.unmodifiableCollection(result);
31+
}
32+
}

‎extensions/security-jpa/deployment/src/main/java/io/quarkus/security/jpa/deployment/QuarkusSecurityJpaProcessor.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
importorg.jboss.jandex.Index;
2727
importorg.jboss.jandex.Type;
2828

29+
importio.quarkus.arc.deployment.AdditionalBeanBuildItem;
2930
importio.quarkus.arc.deployment.GeneratedBeanBuildItem;
3031
importio.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
3132
importio.quarkus.arc.deployment.InjectionPointTransformerBuildItem;
@@ -55,6 +56,7 @@
5556
importio.quarkus.security.jpa.common.deployment.PanacheEntityPredicateBuildItem;
5657
importio.quarkus.security.jpa.runtime.JpaIdentityProvider;
5758
importio.quarkus.security.jpa.runtime.JpaTrustedIdentityProvider;
59+
importio.quarkus.security.jpa.runtime.SecurityJpaImpl;
5860

5961
classQuarkusSecurityJpaProcessor {
6062

@@ -118,6 +120,11 @@ PanacheEntityPredicateBuildItem panacheEntityPredicate(List<PanacheEntityClasses
118120
returnnewPanacheEntityPredicateBuildItem(collectPanacheEntities(panacheEntityClasses));
119121
}
120122

123+
@BuildStep
124+
AdditionalBeanBuildItemregisterSecurityJpaImplCdiBean() {
125+
returnAdditionalBeanBuildItem.unremovableOf(SecurityJpaImpl.class);
126+
}
127+
121128
privateSet<String>collectPanacheEntities(List<PanacheEntityClassesBuildItem>panacheEntityClassesBuildItems) {
122129
Set<String>modelClasses =newHashSet<>();
123130
for (PanacheEntityClassesBuildItempanacheEntityClasses :panacheEntityClassesBuildItems) {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp