버전 : 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 |