티스토리 뷰
이번 글에서는 Thymeleaf 에서 Spring Security 를 사용하는 방법에 대해 살펴보겠습니다. Spring Security 는 전역으로 한 번 설정해두었을 때 권한 별로 화면에서 보여지는 내용을 다르게 표시할 수 있습니다. 이를 위해서는 gradle 파일 내에 아래와 같이 의존성 주입을 해줍니다.
1. build.gradle
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
그리고 namespace 라는 내용이 있습니다. html 태그 안에 추가를 하는 내용이고, 네임스페이스에서 특정 타임리프의 문법을 사용할 것을 선언합니다.
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
우리는 타임리프 문법에서 tag property 앞에 'th:'라는 타임리프 네임스페이스를 이미 쓰고있었습니다. 바로 xmlns:th 선언이 되어 있기 때문입니다.
이제 시큐리티를 타임리프에서 사용할 준비가 끝났습니다. 다음으로는 사용 방법과 예시를 한 번 살펴보겠습니다.
2. Principal 클래스 참조 사용 방법
사용하는 방법은 타임리프와 같습니다. 'th:value', 'th:text' 와 같이 사용하던대로 'sec:authentication' 를 앞에 붙이기만 하면 됩니다.
<span sec:authentication="name"></span>
문법 | 인터페이스 객체 | 내용 |
sec:authentication="name" | Principal | username 을 리턴 |
Principal 객체는 아래와 같이 선언된 인터페이스입니다.
package java.security;
import javax.security.auth.Subject;
public interface Principal {
public boolean equals(Object another);
public String toString();
public int hashCode();
public String getName();
}
아래의 인터페이스를 상속받아 구현 클래스를 만들면 더 호환이 좋게 사용할 수 있습니다.
import java.security.Principal;
@Getter
@NoArgsConstructor
public class UserPrincipal implements Principal {
private final Integer id;
private String name;
private String email;
private final Collection<? extends GrantedAuthority> authorities;
public UserPrincipal(Integer id, String name, String email,
Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.name = name;
this.email = email;
this.authorities = authorities;
}
}
그리고 위에서 구현한 객체는 아래처럼 사용가능한 문법으로 바뀝니다.
ID: <span sec:authentication="principal.id"></span><br>
Name: <span sec:authentication="principal.name"></span><br>
이메일: <span sec:authentication="principal.email"></span>
여기서 IntelliJ 의 경우 principal 객체를 찾기 위해 Cmd 키를 누르고 클릭을 하게 되면 아래 Authentication 객체의 getPrincipal() 메소드가 찍히게 됩니다.
package org.springframework.security.core;
import java.io.Serializable;
import java.security.Principal;
import java.util.Collection;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
3. SecurityExpressionRoot 참조하기
이번에는 아래의 태그들을 사용하는 법을 알아보겠습니다.
<span sec:authorize="isAuthenticated()"></span> // 로그인하여 인증된 사용자
<span sec:authorize="isAnonymous()"></span> // 로그인하지 않은 사용자
<span sec:authorize="hasRole('ROLE_ADMIN')"></span> // ROLE_ADMIN을 가진 사용자
<span sec:authorize="hasAnyRole('ROLE_ADMIN', 'ROLE_MANAGER')"></span> // ROLE_ADMIN 또는
ROLE_MANAGER 권한중 하나 이상 가진 사용자
해당 클래스의 구현체는 아래의 추상클래스에 표시되어 있습니다.
package org.springframework.security.access.expression;
import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
/**
* Base root object for use in Spring Security expression evaluations.
*
* @author Luke Taylor
* @since 3.0
*/
public abstract class SecurityExpressionRoot implements SecurityExpressionOperations
이를 알기 위해서는 가장 먼저 Spring Security 의 Role에 대하여 알아야 합니다. Spring Security는 로그인에 성공하게 되어 인증이 완료되면 Set<Role> 이라는 권한을 가지게 되는데 이 부분은 시큐리티에 대한 글을 따로 올리도록 하겠습니다.
오늘은 이렇게 Spring Security의 내용과 Thymeleaf 를 연관짓는 방법에 대해 간단히 끄적여보았습니다. 스프링 시큐리티는 알면 알수록 편리하게 인증을 도와주는 도구로 활용이 가능한 것 같습니다. 조금 더 파봐야겠습니다!
'Client' 카테고리의 다른 글
[JS] 이미지 프리뷰 적용하기 (0) | 2022.12.06 |
---|---|
[Java] Full Calendar 추가 옵션 내용 (0) | 2022.10.21 |
[JavaScript] Full Calendar 사용방법과 내가 삽질한 내용 (0) | 2022.10.19 |
HTML5 의 data-attr를 잘 활용해보기 (0) | 2022.09.07 |
DataTable.js 의 애프터 렌더링 이벤트 적용하기 (0) | 2022.09.06 |
[Next.js] Rewrite 사용하기 (0) | 2022.01.12 |