keycloak

keycloak - 커스텀 회원가입

몽게구름 2025. 12. 6. 20:00

버전 : keycloak :26.4.7

 

register.ftl

<#import "template.ftl" as layout>

<@layout.registrationLayout displayInfo=false; section>

    <#if section = "header">
        <!-- header hidden -->
    </#if>

    <#if section = "form">

        <div class="mok-page">

            <!-- 로고 -->
            <div class="mok-logo-wrap">
                <img src="${url.resourcesPath}/img/mockio-logo.png"
                     class="mok-logo" alt="mockio">
            </div>

            <!-- 카드 -->
            <div class="mok-card">
                <div class="mok-body">

                    <!-- 전역 에러 (필드 이외 에러) -->
                    <#if message?has_content && !messagesPerField?has_content>
                        <div class="mok-error">
                            ${kcSanitize(message.summary)?no_esc}
                        </div>
                    </#if>

                    <form id="kc-register-form" action="${url.registrationAction}" method="post">

                        <!-- 아이디 -->
                        <#assign usernameError = messagesPerField.exists('username')>
                        <div class="mok-field">
                            <input type="text"
                                   id="username"
                                   name="username"
                                   placeholder="아이디"
                                   value="${(register.formData.username!'')}"
                                   class="<#if usernameError>mok-input-error</#if>"
                            />
                            <#if usernameError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('username'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 성(lastName) -->
                        <#assign lastNameError = messagesPerField.exists('lastName')>
                        <div class="mok-field">
                            <input type="text"
                                   id="lastName"
                                   name="lastName"
                                   placeholder="성"
                                   value="${(register.formData.lastName!'')}"
                                   class="<#if lastNameError>mok-input-error</#if>"
                            />
                            <#if lastNameError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('lastName'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 이름(firstName) -->
                        <#assign firstNameError = messagesPerField.exists('firstName')>
                        <div class="mok-field">
                            <input type="text"
                                   id="firstName"
                                   name="firstName"
                                   placeholder="이름"
                                   value="${(register.formData.firstName!'')}"
                                   class="<#if firstNameError>mok-input-error</#if>"
                            />
                            <#if firstNameError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('firstName'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 이메일 -->
                        <#assign emailError = messagesPerField.exists('email')>
                        <div class="mok-field">
                            <input type="email"
                                   id="email"
                                   name="email"
                                   placeholder="이메일"
                                   value="${(register.formData.email!'')}"
                                   class="<#if emailError>mok-input-error</#if>"
                            />
                            <#if emailError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('email'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 비밀번호 -->
                        <#assign passwordError = messagesPerField.exists('password')>
                        <div class="mok-field">
                            <input type="password"
                                   id="password"
                                   name="password"
                                   placeholder="비밀번호"
                                   class="<#if passwordError>mok-input-error</#if>"
                            />
                            <#if passwordError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('password'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 비밀번호 확인 -->
                        <#assign confirmError = messagesPerField.exists('password-confirm')>
                        <div class="mok-field">
                            <input type="password"
                                   id="password-confirm"
                                   name="password-confirm"
                                   placeholder="비밀번호 확인"
                                   class="<#if confirmError>mok-input-error</#if>"
                            />
                            <#if confirmError>
                                <div class="mok-field-error-text">
                                    ${kcSanitize(messagesPerField.get('password-confirm'))?no_esc}
                                </div>
                            </#if>
                        </div>

                        <!-- 버튼 -->
                        <button type="submit" class="mok-btn">회원가입</button>

                    </form>

                </div>
            </div>
        </div>

    </#if>

</@layout.registrationLayout>

 

 

messages_ko.properties

error-invalid-length=길이는 {1}자 이상 {2}자 이하여야 합니다.
error-invalid-length-too-short=최소 길이는 {1}자입니다.
error-invalid-length-too-long=최대 길이는 {2}자입니다.

error-username-invalid-character=아이디에 허용되지 않는 문자가 포함되어 있습니다.

missingUsernameMessage=아이디를 입력해주세요.
missingEmailMessage=이메일을 입력해 주세요.
missingLastNameMessage=성을 입력해 주세요.
missingFirstNameMessage=이름을 입력해 주세요.
missingPasswordMessage=비밀번호를 입력해 주세요.

missingPasswordConfirmMessage=비밀번호 확인을 입력해 주세요.

usernameExistsMessage=이미 사용 중인 아이디입니다.
emailExistsMessage=이미 사용 중인 이메일입니다.

invalidPasswordExistingMessage=현재 비밀번호가 맞지 않습니다.
invalidPasswordConfirmMessage=비밀번호와 비밀번호 확인이 일치하지 않습니다.
invalidEmailMessage=올바른 이메일 주소를 입력해 주세요.


# --- 비밀번호 길이 ---
invalidPasswordMinLengthMessage=비밀번호가 너무 짧습니다. 최소 {0}자 이상이어야 합니다.
invalidPasswordMaxLengthMessage=비밀번호가 너무 깁니다. 최대 {0}자 이하여야 합니다.

# --- 숫자 / 특수문자 ---
invalidPasswordMinDigitsMessage=비밀번호에는 숫자가 최소 {0}개 포함되어야 합니다.
invalidPasswordMinSpecialCharsMessage=비밀번호에는 특수문자가 최소 {0}개 포함되어야 합니다.

# --- 이메일 / 재사용 / 정규식 ---
invalidPasswordNotEmailMessage=비밀번호는 이메일 주소와 같을 수 없습니다.
invalidPasswordNotRecentlyUsedMessage=비밀번호는 최근 사용한 {0}개의 비밀번호와 달라야 합니다.
invalidPasswordRegexPatternMessage=비밀번호 형식이 보안 규칙을 만족하지 않습니다.

# --- 만료 관련 ---
passwordExpiredMessage=비밀번호가 만료되었습니다. 새 비밀번호로 변경해 주세요.

error-user-attribute-required=값을 입력해 주세요.

 

 

파일 설정은 이렇게만 진행을 하면 되지만

keycloak admin에서 설정할게 몇개 있다.

 

 

Realm settings -> Login 

User registration 을 on 시킵니다.

 

그렇게 되면 로그인 화면에 회원가입 버튼이 활성화 됩니다.

클릭을 하여 회원가입 화면으로 이동 가능합니다.

 

 

회원가입 유효성 검사

 

Authentication -> policies - > password policy 에서 사용하고자 하는 유효성 설정을 합니다.

Expire Password (비밀번호 만료 기간)

  • 비밀번호가 얼마나 오래 사용할 수 있는지 설정합니다.
  • 예: 90 → 90일이 지나면 비밀번호를 다시 변경해야 합니다.

Not Recently Used (최근 사용한 비밀번호 금지)

  • 사용자가 비밀번호를 변경할 때
    최근에 사용했던 비밀번호 몇 개를 다시 사용하지 못하게 하는지 설정합니다.
  • 예: 3 → 최근 3개의 비밀번호는 다시 사용할 수 없음.

Minimum Length (최소 길이)

  • 비밀번호 최소 길이.
  • 예: 8 → 비밀번호는 최소 8자 이상이어야 함.

Special Characters

특수문자 최소 개수

  • 예: 1
    → 비밀번호에 !@#$%^&* 같은 특수문자 적어도 1개 이상 필요

Digits

숫자 최소 개수

  • 예: 1
    → 비밀번호에 숫자 최소 1개 필요 (0~9)

Not Email

비밀번호가 이메일과 동일하면 안 됨

  • 스위치가 OFF → 비활성화
  • 켜면:
    → 비밀번호가 사용자의 이메일과 같은 문자열이면 안 됩니다.

Regular Expression (정규식)

비밀번호가 정규식을 만족해야 함

지금 입력된 정규식: 같은 문자가 세 번 이상 연속 반복되면 안 됨

 

Maximum Length

비밀번호 최대 길이

  • 예: 20
    → 비밀번호는 최대 20자 이하만 허용.

Not Username

비밀번호가 아이디와 동일하면 안 됨

  • 스위치가 OFF → 비활성화
  • 켜면:
    → 비밀번호가 사용자의 아이디와 같은 문자열이면 안 됩니다.

'keycloak' 카테고리의 다른 글

keycloak 구글/네이버 로그인  (0) 2025.12.07
[keycloak] 로그인 화면 꾸미기  (0) 2025.12.06