एक स्प्रिंग बूट प्रोजेक्ट में हमने स्प्रिंग सिक्योरिटी को सक्षम किया और निम्नलिखित लेखों में वर्णित बियरर टोकन के साथ कीक्लोक प्रमाणीकरण लागू किया:

https://www.keycloak.org/docs/3.2/securing_apps/topics/oidc/java/spring-security-adapter.html

https://www.keycloak.org/docs/3.2/securing_apps/topics/oidc/java/spring-boot-adapter.html

लेकिन मुझे कोई सिफारिश नहीं मिल रही है कि स्वचालन परीक्षण कैसे करें ताकि कीक्लोक कॉन्फ़िगरेशन लागू हो।

तो, स्प्रिंग सुरक्षा सक्षम होने पर कीक्लोक कॉन्फ़िगरेशन का परीक्षण/नकली/सत्यापन कैसे करें? वास्तव में एक कष्टप्रद बात: डिफ़ॉल्ट रूप से स्प्रिंग csrf सुरक्षा फ़िल्टर को सक्रिय करता है, लेकिन इसका परीक्षण करने से कैसे बचें?

(नोट: हम वाहक टोकन का उपयोग करते हैं, इसलिए ऐसा लगता है कि @WithMockUser इस मामले में लागू नहीं है)

एक बोनस प्रश्न: मूल रूप से हम प्रत्येक नियंत्रक एकीकरण परीक्षण पर सुरक्षा सत्यापित नहीं करना चाहते हैं, इसलिए क्या नियंत्रक एकीकरण परीक्षण (जो @SpringBootTest, @WebAppConfiguration, @AutoConfigureMockMvc और का उपयोग करते हैं, से सुरक्षा को अलग से सत्यापित करना संभव है। जल्द ही?

13
radistao 6 अगस्त 2018, 18:41

3 जवाब

एक समाधान कीक्लोक प्राधिकरण सर्वर को स्टब करने के लिए WireMock का उपयोग कर रहा है। इसलिए आप पुस्तकालय का उपयोग कर सकते हैं spring-cloud-contract-wiremock(देखें https://cloud.spring.io/spring-cloud-contract/1.1.x/multi/multi__spring_cloud_contract_wiremock.html), जो एक आसान स्प्रिंग बूट एकीकरण प्रदान करता है। जैसा कि वर्णित है आप निर्भरता को आसानी से जोड़ सकते हैं। इसके अलावा मैं नकली एक्सेस टोकन बनाने के लिए उसी तरह jose4j का उपयोग करता हूं जैसे Keycloak JWTs की तरह करता है। आपको बस इतना करना है कि कीक्लोक ओपनआईडी कॉन्फ़िगरेशन और JSON वेब कुंजी संग्रहण के लिए समापन बिंदुओं को दबा देना है, क्योंकि कीक्लोक एडेप्टर केवल उन्हीं का अनुरोध करता है जो प्राधिकरण शीर्षलेख में पहुंच टोकन के सत्यापन के लिए हैं।

एक न्यूनतम कामकाजी स्टैंडअलोन उदाहरण, जिसे एक ही स्थान पर अनुकूलित करने की आवश्यकता है (देखें महत्वपूर्ण नोट्स), कुछ स्पष्टीकरणों के साथ निम्नलिखित में सूचीबद्ध है:

KeycloakTest.java:

@ExtendWith(SpringExtension.class)
@WebMvcTest(KeycloakTest.TestController.class)
@EnableConfigurationProperties(KeycloakSpringBootProperties.class)
@ContextConfiguration(classes= {KeycloakTest.TestController.class, SecurityConfig.class, CustomKeycloakSpringBootConfigResolver.class})
@AutoConfigureMockMvc
@AutoConfigureWireMock(port = 0) //random port, that is wired into properties with key wiremock.server.port
@TestPropertySource(locations = "classpath:wiremock.properties")
public class KeycloakTest {

    private static RsaJsonWebKey rsaJsonWebKey;

    private static boolean testSetupIsCompleted = false;

    @Value("${wiremock.server.baseUrl}")
    private String keycloakBaseUrl;

    @Value("${keycloak.realm}")
    private String keycloakRealm;

    @Autowired
    private MockMvc mockMvc;

    @BeforeEach
    public void setUp() throws IOException, JoseException {
        if(!testSetupIsCompleted) {
            // Generate an RSA key pair, which will be used for signing and verification of the JWT, wrapped in a JWK
            rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
            rsaJsonWebKey.setKeyId("k1");
            rsaJsonWebKey.setAlgorithm(AlgorithmIdentifiers.RSA_USING_SHA256);
            rsaJsonWebKey.setUse("sig");

            String openidConfig = "{\n" +
                    "  \"issuer\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "\",\n" +
                    "  \"authorization_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/auth\",\n" +
                    "  \"token_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token\",\n" +
                    "  \"token_introspection_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token/introspect\",\n" +
                    "  \"userinfo_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/userinfo\",\n" +
                    "  \"end_session_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/logout\",\n" +
                    "  \"jwks_uri\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/certs\",\n" +
                    "  \"check_session_iframe\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/login-status-iframe.html\",\n" +
                    "  \"registration_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/clients-registrations/openid-connect\",\n" +
                    "  \"introspection_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token/introspect\"\n" +
                    "}";
            stubFor(WireMock.get(urlEqualTo(String.format("/auth/realms/%s/.well-known/openid-configuration", keycloakRealm)))
                    .willReturn(aResponse()
                            .withHeader("Content-Type", "application/json")
                            .withBody(openidConfig)
                    )
            );
            stubFor(WireMock.get(urlEqualTo(String.format("/auth/realms/%s/protocol/openid-connect/certs", keycloakRealm)))
                    .willReturn(aResponse()
                            .withHeader("Content-Type", "application/json")
                            .withBody(new JsonWebKeySet(rsaJsonWebKey).toJson())
                    )
            );
            testSetupIsCompleted = true;
        }
    }

    @Test
    public void When_access_token_is_in_header_Then_process_request_with_Ok() throws Exception {
        ResultActions resultActions = this.mockMvc
                .perform(get("/test")
                        .header("Authorization",String.format("Bearer %s", generateJWT(true)))
                );
        resultActions
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string("hello"));
    }

    @Test
    public void When_access_token_is_missing_Then_redirect_to_login() throws Exception {
        ResultActions resultActions = this.mockMvc
                .perform(get("/test"));
        resultActions
                .andDo(print())
                .andExpect(status().isFound())
                .andExpect(redirectedUrl("/sso/login"));
    }

    private String generateJWT(boolean withTenantClaim) throws JoseException {

        // Create the Claims, which will be the content of the JWT
        JwtClaims claims = new JwtClaims();
        claims.setJwtId(UUID.randomUUID().toString()); // a unique identifier for the token
        claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now)
        claims.setNotBeforeMinutesInThePast(0); // time before which the token is not yet valid (2 minutes ago)
        claims.setIssuedAtToNow(); // when the token was issued/created (now)
        claims.setAudience("account"); // to whom this token is intended to be sent
        claims.setIssuer(String.format("%s/auth/realms/%s",keycloakBaseUrl,keycloakRealm)); // who creates the token and signs it
        claims.setSubject(UUID.randomUUID().toString()); // the subject/principal is whom the token is about
        claims.setClaim("typ","Bearer"); // set type of token
        claims.setClaim("azp","example-client-id"); // Authorized party  (the party to which this token was issued)
        claims.setClaim("auth_time", NumericDate.fromMilliseconds(Instant.now().minus(11, ChronoUnit.SECONDS).toEpochMilli()).getValue()); // time when authentication occured
        claims.setClaim("session_state", UUID.randomUUID().toString()); // keycloak specific ???
        claims.setClaim("acr", "0"); //Authentication context class
        claims.setClaim("realm_access", Map.of("roles",List.of("offline_access","uma_authorization","user"))); //keycloak roles
        claims.setClaim("resource_access", Map.of("account",
                    Map.of("roles", List.of("manage-account","manage-account-links","view-profile"))
                )
        ); //keycloak roles
        claims.setClaim("scope","profile email");
        claims.setClaim("name", "John Doe"); // additional claims/attributes about the subject can be added
        claims.setClaim("email_verified",true);
        claims.setClaim("preferred_username", "doe.john");
        claims.setClaim("given_name", "John");
        claims.setClaim("family_name", "Doe");

        // A JWT is a JWS and/or a JWE with JSON claims as the payload.
        // In this example it is a JWS so we create a JsonWebSignature object.
        JsonWebSignature jws = new JsonWebSignature();

        // The payload of the JWS is JSON content of the JWT Claims
        jws.setPayload(claims.toJson());

        // The JWT is signed using the private key
        jws.setKey(rsaJsonWebKey.getPrivateKey());

        // Set the Key ID (kid) header because it's just the polite thing to do.
        // We only have one key in this example but a using a Key ID helps
        // facilitate a smooth key rollover process
        jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());

        // Set the signature algorithm on the JWT/JWS that will integrity protect the claims
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);

        // set the type header
        jws.setHeader("typ","JWT");

        // Sign the JWS and produce the compact serialization or the complete JWT/JWS
        // representation, which is a string consisting of three dot ('.') separated
        // base64url-encoded parts in the form Header.Payload.Signature
        return jws.getCompactSerialization();
    }

    @RestController
    public static class TestController {
        @GetMapping("/test")
        public String test() {
            return "hello";
        }
    }

}

wiremock.properties:

wiremock.server.baseUrl=http://localhost:${wiremock.server.port}
keycloak.auth-server-url=${wiremock.server.baseUrl}/auth

परीक्षण व्यवस्था

एनोटेशन @AutoConfigureWireMock(port = 0) एक रैंडम पोर्ट पर एक वायरमॉक सर्वर शुरू करेगा, जो स्वचालित रूप से संपत्ति wiremock.server.port पर सेट हो जाता है, इसलिए इसका उपयोग स्प्रिंग बूट कीक्लोक एडेप्टर के लिए keycloak.auth-server-url संपत्ति को ओवरराइड करने के लिए किया जा सकता है। तदनुसार (देखें wiremock.properties)

JWT उत्पन्न करने के लिए, जिसका उपयोग पहुंच टोकन के रूप में किया जाता है, मैं jose4j के साथ एक RSA कुंजी जोड़ी बनाता हूं, जिसे एक परीक्षण के रूप में घोषित किया जाता है क्लास विशेषता, क्योंकि मुझे वायरमॉक सर्वर के साथ परीक्षण सेटअप के दौरान इसे प्रारंभ करने की आवश्यकता है।

private static RsaJsonWebKey rsaJsonWebKey;

इसके बाद परीक्षण सेटअप के दौरान इसे निम्न के रूप में प्रारंभ किया जाता है:

rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
            rsaJsonWebKey.setKeyId("k1");
            rsaJsonWebKey.setAlgorithm(AlgorithmIdentifiers.RSA_USING_SHA256);
            rsaJsonWebKey.setUse("sig");

keyId का चुनाव कोई मायने नहीं रखता। आप जो चाहें चुन सकते हैं, जब तक वह सेट है। हालांकि चुना हुआ एल्गोरिदम और उपयोग मायने रखता है और इसे बिल्कुल उदाहरण के रूप में अनुकूलित किया जाना चाहिए।

इसके साथ JSON वेब कुंजी संग्रहण कीक्लोक स्टब का समापन बिंदु तदनुसार निम्नानुसार सेट किया जा सकता है:

stubFor(WireMock.get(urlEqualTo(String.format("/auth/realms/%s/protocol/openid-connect/certs", keycloakRealm)))
                    .willReturn(aResponse()
                            .withHeader("Content-Type", "application/json")
                            .withBody(new JsonWebKeySet(rsaJsonWebKey).toJson())
                    )
            );

इसके अलावा एक अन्य समापन बिंदु को कीक्लोक के लिए स्टब करने की आवश्यकता है जैसा कि पहले उल्लेख किया गया है। यदि कैश्ड नहीं है, तो कीक्लोक एडेप्टर को ओपनिड कॉन्फ़िगरेशन का अनुरोध करने की आवश्यकता है। कम से कम काम करने वाले उदाहरण के लिए सभी एंडपॉइंट्स को कॉन्फ़िगरेशन में परिभाषित करने की आवश्यकता होती है, जो कि OpenId कॉन्फ़िगरेशन एंडपॉइंट से लौटाया जाता है:

String openidConfig = "{\n" +
                    "  \"issuer\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "\",\n" +
                    "  \"authorization_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/auth\",\n" +
                    "  \"token_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token\",\n" +
                    "  \"token_introspection_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token/introspect\",\n" +
                    "  \"userinfo_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/userinfo\",\n" +
                    "  \"end_session_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/logout\",\n" +
                    "  \"jwks_uri\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/certs\",\n" +
                    "  \"check_session_iframe\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/login-status-iframe.html\",\n" +
                    "  \"registration_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/clients-registrations/openid-connect\",\n" +
                    "  \"introspection_endpoint\": \"" + keycloakBaseUrl + "/auth/realms/" + keycloakRealm + "/protocol/openid-connect/token/introspect\"\n" +
                    "}";
stubFor(WireMock.get(urlEqualTo(String.format("/auth/realms/%s/.well-known/openid-configuration", keycloakRealm)))
                    .willReturn(aResponse()
                            .withHeader("Content-Type", "application/json")
                            .withBody(openidConfig)
                    )
            );

टोकन जनरेशन

टोकन का निर्माण generateJWT() में jose4j के भारी उपयोग के साथ लागू किया गया है। यहां ध्यान देने योग्य सबसे महत्वपूर्ण बात यह है कि उसी की निजी कुंजी JWK के रूप में उत्पन्न होती है वायरमॉक के लिए परीक्षण सेटअप के दौरान आरंभ किए गए एक का उपयोग किया जाना है।

jws.setKey(rsaJsonWebKey.getPrivateKey());

इसके अलावा कोड मुख्य रूप से https://bitbucket.org/ पर उदाहरण से अनुकूलित किया गया है। b_c/jose4j/wiki/JWT%20उदाहरण
कोई अब अपने स्वयं के विशिष्ट परीक्षण सेटअप के लिए उपयुक्त समझे जाने वाले दावों को समायोजित या बढ़ा सकता है। पोस्ट किए गए स्निपेट में न्यूनतम उदाहरण Keycloak द्वारा निर्मित JWT के लिए एक विशिष्ट उदाहरण का प्रतिनिधित्व करता है।

परीक्षण निष्पादन

जेनरेट किए गए JWT का उपयोग हमेशा की तरह प्राधिकरण हेडर में REST एंडपॉइंट पर अनुरोध भेजने के लिए किया जा सकता है:

ResultActions resultActions = this.mockMvc
                .perform(get("/test")
                        .header("Authorization",String.format("Bearer %s", generateJWT(true)))
                );

एक स्टैंडअलोन उदाहरण का प्रतिनिधित्व करने के लिए परीक्षण वर्ग में एक साधारण रेस्टकंट्रोलर होता है जिसे आंतरिक वर्ग के रूप में परिभाषित किया जाता है, जिसका उपयोग परीक्षण के लिए किया जाता है।

@RestController
public static class TestController {
    @GetMapping("/test")
    public String test() {
        return "hello";
    }
}

महत्वपूर्ण लेख

मैंने परीक्षण उद्देश्यों के लिए एक कस्टम TestController पेश किया था, इसलिए इसे WebMvcTest में लोड करने के लिए एक कस्टम कॉन्टेक्स्ट कॉन्फ़िगरेशन को परिभाषित करना आवश्यक था:

@ContextConfiguration(classes= {KeycloakTest.TestController.class, SecurityConfig.class, CustomKeycloakSpringBootConfigResolver.class})

टेस्टकंट्रोलर के अलावा स्प्रिंग सिक्योरिटी और कीक्लोक एडेप्टर के संबंध में कॉन्फ़िगरेशन बीन्स का एक गुच्छा SecurityConfig.class और CustomKeycloakSpringBootConfigResolver.class जैसे काम करने के लिए शामिल है। इन्हें निश्चित रूप से आपके स्वयं के कॉन्फ़िगरेशन द्वारा प्रतिस्थापित करने की आवश्यकता है। पूर्णता के लिए उन वर्गों को भी निम्नलिखित में सूचीबद्ध किया जाएगा:

SecurityConfig.java:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
        grantedAuthorityMapper.setPrefix("ROLE_");

        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    /*
     * Workaround for reading the properties for the keycloak adapter (see https://stackoverflow.com/questions/57787768/issues-running-example-keycloak-spring-boot-app)
     */
    @Bean
    @Primary
    public KeycloakConfigResolver keycloakConfigResolver(KeycloakSpringBootProperties properties) {
        return new CustomKeycloakSpringBootConfigResolver(properties);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    @Override
    @ConditionalOnMissingBean(HttpSessionManager.class)
    protected HttpSessionManager httpSessionManager() {
        return new HttpSessionManager();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers("/**").hasRole("user")
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
}

CustomKeycloakSpringBootConfigResolver.java:

 /*
  * Workaround for reading the properties for the keycloak adapter (see https://stackoverflow.com/questions/57787768/issues-running-example-keycloak-spring-boot-app)
  */
@Configuration
public class CustomKeycloakSpringBootConfigResolver extends KeycloakSpringBootConfigResolver {
    private final KeycloakDeployment keycloakDeployment;

    public CustomKeycloakSpringBootConfigResolver(KeycloakSpringBootProperties properties) {
        keycloakDeployment = KeycloakDeploymentBuilder.build(properties);
    }

    @Override
    public KeycloakDeployment resolve(HttpFacade.Request facade) {
        return keycloakDeployment;
    }
}
1
Tamim 25 फरवरी 2020, 18:07

केवल "बोनस" प्रश्न पर लागू होने वाला आंशिक उत्तर (@Component यूनिट-टेस्ट): मैंने अभी-अभी libs का एक सेट लिखा है सुरक्षित स्प्रिंग ऐप्स के यूनिट-परीक्षण को आसान बनाने के लिए। मैं केवल ऐसे परीक्षण और e2e परीक्षण चलाता हूं (समृद्ध क्लाइंट फ्रंट-एंड और वास्तविक प्राधिकरण-सर्वर सहित)।

इसमें एक @WithMockKeycloackAuth एनोटेशन के साथ-साथ Keycloak समर्पित MockMvc अनुरोध पोस्ट-प्रोसेसर शामिल है

नमूना उपयोग:

@RunWith(SpringRunner.class)
@WebMvcTest(GreetingController.class)
@ContextConfiguration(classes = GreetingApp.class)
@ComponentScan(basePackageClasses = { KeycloakSecurityComponents.class, KeycloakSpringBootConfigResolver.class })
public class GreetingControllerTests extends ServletUnitTestingSupport {
    @MockBean
    MessageService messageService;

    @Test
    @WithMockKeycloackAuth("TESTER")
    public void whenUserIsNotGrantedWithAuthorizedPersonelThenSecretRouteIsNotAccessible() throws Exception {
        mockMvc().get("/secured-route").andExpect(status().isForbidden());
    }

    @Test
    @WithMockKeycloackAuth("AUTHORIZED_PERSONNEL")
    public void whenUserIsGrantedWithAuthorizedPersonelThenSecretRouteIsAccessible() throws Exception {
        mockMvc().get("/secured-route").andExpect(content().string(is("secret route")));
    }

    @Test
    @WithMockKeycloackAuth(name = "ch4mpy", roles = "TESTER")
    public void whenGreetIsReachedWithValidSecurityContextThenUserIsActuallyGreeted() throws Exception {
        when(messageService.greet(any())).thenAnswer(invocation -> {
            final var auth = (Authentication) invocation.getArgument(0);
            return String.format("Hello %s! You are granted with %s.", auth.getName(),
                    auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
        });

        mockMvc().get("/greet").andExpect(content().string(is("Hello ch4mpy! You are granted with [ROLE_TESTER].")));
    }
}

मेवेन-सेंट्रल से अलग-अलग lib उपलब्ध हैं, अपने उपयोग-मामले के अनुसार निम्न में से एक चुनें:

<dependency>
  <groupId>com.c4-soft.springaddons</groupId>
  <artifactId>spring-security-oauth2-test-webmvc-addons</artifactId>
  <version>2.0.3</version>
  <scope>test</test>
</dependency>
<dependency>
  <groupId>com.c4-soft.springaddons</groupId>
  <artifactId>spring-security-oauth2-test-webflux-addons</artifactId>
  <version>2.0.3</version>
  <scope>test</test>
</dependency>
1
ch4mp 6 अप्रैल 2020, 23:15

मैं एक्टिविटी प्रोजेक्ट पर काम करता हूं और हम स्प्रिंग बूट के साथ कीक्लोक का उपयोग कर रहे हैं और उसी प्रश्न को हिट करते हैं। KeycloakSecurityContextClientRequestInterceptor जिसे हमने थोड़ा सा अनुकूलित किया है। यह परीक्षण के लिए उपयोग करने के लिए दायरे और उपयोगकर्ता का संदर्भ देता है। हम " rel="nofollow noreferrer">उन गुणों को परीक्षण में सेट करें जो कीक्लोक का उपयोग करते हैं। इसका उपयोग परीक्षणों के एक सेट के दौरान उपयोगकर्ताओं को स्विच करें

उन परीक्षणों के लिए जहां हम कीक्लोक का उपयोग नहीं करना चाहते हैं, हमने अब तक अपनी परियोजना में उन्हें एक अलग स्तर पर रखने की प्रथा का पालन किया है और इसलिए एक अलग सबमॉड्यूल में। यह हमें कीक्लोक मावेन निर्भरता को उस परत से बाहर रखने देता है ताकि कीक्लोक बस उन पर सक्षम न हो।

0
Ryan Dawson 7 अगस्त 2018, 15:23
उचित समाधान नहीं दिखता क्योंकि testUser और testPassword मुख्य स्रोतों में लागू हैं, जिनसे मैं बचना चाहता हूं।
 – 
radistao
8 अगस्त 2018, 12:28
निष्पक्ष बिंदु। आप परीक्षण के लिए एक अलग क्षेत्र का उपयोग कर सकते हैं ताकि वह विशेष उपयोगकर्ता आपके लाइव सिस्टम पर दायरे में शामिल न हो या संभवतः उस उपयोगकर्ता को जोड़ने के लिए एक स्क्रिप्ट का उपयोग करें जब परीक्षण के लिए उपयोग किया जाने वाला डॉकटर कंटेनर शुरू होता है। मैं यह बताना भूल गया कि कीक्लोक का उपयोग करने वाले परीक्षण एक कीक्लोक डॉकटर कंटेनर के खिलाफ चल रहे हैं जिसे हम डॉकर मावेन प्लगइन से शुरू करते हैं।
 – 
Ryan Dawson
8 अगस्त 2018, 12:52
पासवर्ड को परीक्षण कोड से बाहर निकालने के अन्य विकल्प यह हो सकते हैं कि इसे संपत्ति फ़ाइल के बजाय एक पर्यावरण चर या मावेन चर से सेट किया जाए। या स्प्रिंग बूट jasypt जैसी किसी चीज़ के साथ प्रॉप्स में एन्क्रिप्ट करें।
 – 
Ryan Dawson
14 अगस्त 2018, 10:33
क्षमा करें, मुझे अभी एहसास हुआ कि आपका मतलब है कि हमने KeycloakSecurityContextClientRequestInterceptor को src/main के अंतर्गत रखा है और आप इसे src/test के अंतर्गत चाहते हैं। हम इसे केवल src/main के अंतर्गत रखते हैं ताकि इसे एक पुस्तकालय में रखा जा सके कि हम अन्य भंडारों में पुन: उपयोग कर सकें।
 – 
Ryan Dawson
15 अगस्त 2018, 20:00