게시판 만들기 - 인증기능 구현 (뷰)

정영찬·2022년 9월 5일
0

프로젝트 실습

목록 보기
44/60

이제 인증기능을 뷰에 적용시켜보자.

헤더

로그인 로그아웃 버튼 생성

  <div class="text-end">
                <span id="username" class="text-white me-2">username</span>
                <a role="button" id="login" class="btn btn-outline-light me-2">Login</a>
                <a role="button" id="logout" class="btn btn-outline-light me-2"></a>
            </div>

header.th.sml

<?xml version="1.0"?>
<thlogic xmlns:th="http://www.thymeleaf.org">
    <attr sel="#home" th:href="@{/}"/>
    <attr sel="#hashtag" th:href="@{/articles/search-hashtag}"/>
    <attr sel="#username" sec:authorize="isAuthenticated()" sec:authentication="name"/>
    <attr sel="#login" sec:authorize="!isAuthenticated()" th:href="@{/login}"/>
    <attr sel="#logout" sec:authorize="isAuthenticated()" th:href="@{/logout}"/>
</thlogic>

인증 여부에 따라서 login 버튼, 혹은 logout 버튼을 보여준다.

로그인을 들어가서 유저 계정과 비밀번호를 입력하고 들어가면

PasswordEncoder에 id가 null로 나타났다.

PasswordEncoder는 PasswaordEncoderFactories에서 createDelegatingPasswordEncoder를 사용하는데, 패스워드 데이터 앞머리에 내용을 붙여주지 않으면 인식을 얘가 인식을 하지 못한다. 앞머리에 추가하는 내용은 바로 암호화 규칙으로 여러가지 방식으로 선택이 가능하지만, 지금은 테스트 단계이니 만큼 {noop}을 붙여서 비밀번호가 그대로 보여지게 설정한다. 물론 암호화 규칙을 적용하는것도 좋지만, 비밀번호를 어떤 값으로 지정했는지를 바로 볼수 없는 것이 불편하기 때문이다.

data.sql 파일에서 유저 테스트 데이터의 비밀번호 값의 앞에다가 {noop}를 추가해준다.

이렇게 해주면 로그인이 되서 게시글 페이지로 들어가게 된다.

index

로그인이 되어있는 경우에만 글을 쓸수 있도록 게시판 페이지의 글쓰기 버튼을 인증 여부에 따라 나타나거나 사라지게 설정했다.
index.th.xml

<attr sel="#write-article" sec:authorize="isAuthenticated()" th:href="@{/articles/form}"></attr>

디테일

게시글 페이지의 수정과 삭제버튼은 게시글 작성자와 인증 사용자가 같은 경우에만 나타나게 설정해서 다른 사람들이 수정,삭제를 할수 없게 설정했다.

게시글 페이지의 댓글에 생성된 삭제버튼또한 인증 사용자가 댓글 작성자와 같은 경우에만 삭제를 할수 있어야한다. 따라서 다른 사용자의 댓글에는 삭제라는 버튼이 나타나지 않게 수정했다.
detail.th.xml

        <attr sel="#article-buttons" th:if="${#authorization.expression('isAuthenticated()')} and *{userId} == ${#authentication.name}">
            <attr sel="#delete-article-form" th:action="'/articles/' + *{id} + '/delete'" th:method="post">
                <attr sel="#update-article" th:href="'/articles/' + *{id} + '/form'" />
            </attr>
	...
    
                <attr sel="div/small/time" th:datetime="${articleComment.createdAt}"
                      th:text="${#temporals.format(articleComment.createdAt, 'yyyy-MM-dd HH:mm:ss')}"/>
                <attr sel="div/p" th:text="${articleComment.content}"/>
                    <attr sel="button" th:if="${#authorization.expression('isAuthenticated()')} and ${articleComment.userId} == ${#authentication.name}" />

수정기능 오류

이렇게 뷰까지 만들어서 다 된줄 알았는데 자세히 테스트 해보니 수정 기능이 제대로 동작하지 않았다.
테스트도 전부 통과를 해서 보안 이유로 방어되어서 수정되지 않은 것인줄 알았는데, userAccount 도메인에서 equals()에 오류가 생긴것을 발견했다. userId를 비교하는 내용에서 that.id 같은 표현이 본래의 역할을 수행하고 있지 않아서 userId비교가 되지 않아서 수정되지 않은 것이다. 따라서 제대로 getter를 사용해서 값을 불러오게 수정했고 이름또한 that으로 통일 시켰다.
article

   @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Article that) ) return false;
        return id != null && id.equals(that.getId());
    }

articleComment

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ArticleComment that)) return false;
        return id != null && id.equals(that.getId());
    }

userAccount

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof UserAccount that)) return false;
        return userId != null && userId.equals(that.getUserId());
    }

이제 완벽하게 게시글이 동작한다.

profile
개발자 꿈나무

0개의 댓글