타임리프 스프링 시큐리티
구분 | 키워드/메서드 | 설명 |
sec:authorize | isAnonymous() | 인증되지 않은 사용자(비로그인). |
isAuthenticated() | 인증된 사용자(로그인). | |
hasRole('ROLE_X') | 특정 역할을 가진 사용자. | |
hasAnyRole('ROLE_X', 'ROLE_Y') | 여러 역할 중 하나라도 가진 사용자. | |
permitAll() | 모든 사용자 허용. | |
denyAll() | 모든 사용자 금지. | |
sec:authentication | name | 인증된 사용자의 이름(아이디). |
authorities | 인증된 사용자의 권한 목록. | |
principal | 인증된 사용자 객체
(UserDetails 또는 CustomUser). | |
sec:csrf | ${_csrf.parameterName} | CSRF 파라미터 이름. |
${_csrf.token} | CSRF 토큰 값. |
예시 코드
1. sec:authorize
html
코드 복사
<div sec:authorize="isAnonymous()">
<p>로그인하지 않은 사용자에게만 표시됩니다.</p>
</div>
<div sec:authorize="isAuthenticated()">
<p>로그인한 사용자에게만 표시됩니다.</p>
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p>관리자 전용 콘텐츠입니다.</p>
</div>
<div sec:authorize="hasAnyRole('ROLE_USER', 'ROLE_MANAGER')">
<p>사용자 또는 매니저 권한을 가진 사용자만 볼 수 있습니다.</p>
</div>
<div sec:authorize="permitAll()">
<p>모든 사용자에게 표시됩니다.</p>
</div>
<div sec:authorize="denyAll()">
<p>이 콘텐츠는 어떤 사용자에게도 표시되지 않습니다.</p>
</div>
HTML
복사
2. sec:authentication
html
코드 복사
<p>로그인한 사용자: <span sec:authentication="name"></span></p>
<p>권한 목록: <span sec:authentication="authorities"></span></p>
<p>사용자 이름: <span sec:authentication="principal.user.name"></span></p>
<p>사용자 이메일: <span sec:authentication="principal.user.email"></span></p>
HTML
복사
3. sec:csrf
CSRF 토큰을 포함한 폼
html
코드 복사
<form th:action="@{/submit}" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<button type="submit">제출</button>
</form>
HTML
복사
4. 종합 예제
로그인 상태에 따라 메뉴를 다르게 표시:
html
코드 복사
<div sec:authorize="isAuthenticated()">
<p>환영합니다, <span sec:authentication="name"></span>!</p>
<a th:href="@{/logout}">로그아웃</a>
</div>
<div sec:authorize="isAnonymous()">
<a th:href="@{/login}">로그인</a>
<a th:href="@{/signup}">회원가입</a>
</div>
HTML
복사
관리자와 일반 사용자에 따라 다른 콘텐츠 표시:
html
코드 복사
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p>관리자 전용 페이지입니다.</p>
</div>
<div sec:authorize="hasRole('ROLE_USER')">
<p>사용자 전용 페이지입니다.</p>
</div>
HTML
복사
요약
•
sec:authorize는 사용자 상태와 권한에 따라 콘텐츠를 렌더링합니다.
•
sec:authentication을 사용하여 인증된 사용자 정보를 출력합니다.
•
sec:csrf는 CSRF 보호를 위해 토큰을 포함합니다.
예시코드
•
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>메인 화면</title>
<!-- bootstrap css -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- 헤더 -->
<header class="d-flex flex-wrap align-items-center justify-content-center justify-content-md-between px-5 py-3 mb-4 border-bottom">
<div class="col-md-3 mb-2 mb-md-0">
<a href="/" class="d-inline-flex link-body-emphasis text-decoration-none">
<!-- 로고 -->
</a>
</div>
<ul class="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0">
<li><a href="/" class="nav-link px-2 link-secondary">Home</a></li>
<!-- 사용자 & 관리자 권한 -->
<th:block sec:authorize="hasAnyRole('ROLE_USER','ROLE_ADMIN')">
<li><a href="/user" class="nav-link px-2">user</a></li>
</th:block>
<!-- 관리자 권한 -->
<th:block sec:authorize="hasRole('ROLE_ADMIN')">
<li><a href="/admin" class="nav-link px-2">admin</a></li>
</th:block>
</ul>
<div class="col-md-3 text-end">
<!-- 비로그인 시 -->
<th:block sec:authorize="isAnonymous()">
<a href="/login" class="btn btn-outline-primary me-2">로그인</a>
<a href="/join" class="btn btn-primary me-2">회원가입</a>
</th:block>
<!-- 로그인 시 -->
<th:block sec:authorize="isAuthenticated()">
<form action="/logout" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<button type="submit" class="btn btn-primary">로그아웃</button>
</form>
</th:block>
</div>
</header>
<div class="container col-12 col-lg-4">
<div class="px-4 py-5 mt-5 text-center">
<h1 class="display-5 fw-bold text-body-emphasis">메인 화면</h1>
</div>
<!-- 비 로그인 시 -->
<th:block sec:authorize="isAnonymous()">
<div class="d-grid gap-2">
<a href="/login" class="btn btn-lg btn-primary">로그인</a>
<a href="/join" class="btn btn-lg btn-success">회원가입</a>
</div>
</th:block>
<!-- 로그인 시 -->
<th:block sec:authorize="isAuthenticated()">
<div class="card">
<div class="inner p-4">
<div class="d-flex flex-column align-items-center">
<div class="item my-2">
<h3>
아이디 : <span sec:authentication="name"></span>
</h3>
</div>
<div class="item my-2">
<h3>
권한 : <span sec:authentication="authorities"></span>
</h3>
</div>
<div class="item my-2 w-100">
<p>
사용자 객체 : <span sec:authentication="principal"></span>
</p>
</div>
<!-- ⭐ sec:authentication="principal" ➡ CustomUser -->
<!-- 👩💼 CustomUser 안에 Users user 객체가 있다 -->
<div class="item my-2">
<h5>
이름 : <span sec:authentication="principal.user.name"></span>
</h5>
</div>
<div class="item my-2">
<h5>
이메일 : <span sec:authentication="principal.user.email"></span>
</h5>
</div>
<!-- <div class="item my-2">
<img th:src="${user.profile}" alt="프로필" class="rounded-circle">
</div> -->
<!-- <div class="item my-2">
<h3 th:text="${user.name}"></h3>
</div>
<div class="item my-2">
<h5 th:text="${user.email}"></h5>
</div> -->
<div class="item my-2 w-100">
<span sec:authentication="principal">인증된 사용자</span>
</div>
</div>
</div>
</div>
<form action="/logout" method="post">
<!-- CSRF TOKEN -->
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<div class="d-grid gap-2">
<button type="submit" class="btn btn-lg btn-primary">로그아웃</button>
</div>
</form>
</th:block>
</div>
<!-- bootstrap js -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
HTML
복사








