[Spring] 26. 로그인 / 로그아웃개발자가 되기까지 (2023.08.16~2024.04.15)/[Spring] Basic Web2024. 1. 30. 22:30
Table of Contents
CustomAuthMemberService.java
package com.basicWeb.www.security;
import javax.inject.Inject;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.basicWeb.www.repository.MemberDAO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class CustomAuthMemberService implements UserDetailsService {
@Inject
private MemberDAO mdao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MemberVO mvo = mdao.selectEmail(username);
if(mvo == null) {
throw new UsernameNotFoundException(username);
}
mvo.setAuthList(mdao.selectAuths(username));
log.info(">>> userDetails >>> {}", mvo);
return new AuthMember(mvo);
}
}
loadUserByUsername method는 전달받은 사용자 이름(이 프로젝트에서는 이메일)을 기반으로
데이터베이스에서 해당 사용자의 정보를 조회한다.
MemberController.java
package com.basicWeb.www.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.basicWeb.www.security.MemberVO;
import com.basicWeb.www.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping("/member/*")
public class MemberController {
private final MemberService msv;
private final BCryptPasswordEncoder bcEncoder;
// ... (기존 코드)
@GetMapping("/login")
public void login() {}
@PostMapping("/login")
public String login(HttpServletRequest request, RedirectAttributes re) {
re.addAttribute("email", request.getAttribute("email"));
re.addAttribute("errMsg", request.getAttribute("errMsg"));
return "redirect:/member/login";
}
}
MemberService.interface
package com.basicWeb.www.service;
import com.basicWeb.www.security.MemberVO;
public interface MemberService {
int register(MemberVO mvo);
boolean updateLastLogin(String authEmail);
}
MemberSeriveImpl.java
package com.basicWeb.www.service;
import org.springframework.stereotype.Service;
import com.basicWeb.www.repository.MemberDAO;
import com.basicWeb.www.security.MemberVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberDAO mdao;
@Override
public int register(MemberVO mvo) {
int isOk = mdao.insert(mvo);
return mdao.insertAuthInit(mvo.getEmail());
}
@Override
public boolean updateLastLogin(String authEmail) {
// TODO Auto-generated method stub
return mdao.updateLastLogin(authEmail) > 0 ? true : false;
}
}
MemberDAO.interface
package com.basicWeb.www.repository;
import java.util.List;
import com.basicWeb.www.security.AuthVO;
import com.basicWeb.www.security.MemberVO;
public interface MemberDAO {
int insert(MemberVO mvo);
int insertAuthInit(String email);
MemberVO selectEmail(String username);
List<AuthVO> selectAuths(String username);
int updateLastLogin(String authEmail);
}
memberMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.basicWeb.www.repository.MemberDAO">
<insert id="insert">
INSERT INTO member (email, pwd, nick_name)
VALUES(#{email}, #{pwd}, #{nickName})
</insert>
<insert id="insertAuthInit">
INSERT INTO auth_member
VALUES (#{email}, 'ROLE_USER')
</insert>
<select id="selectEmail" resultType="com.basicWeb.www.security.MemberVO">
SELECT * FROM member WHERE email = #{email}
</select>
<select id="selectAuths" resultType="com.basicWeb.www.security.AuthVO">
SELECT * from auth_member WHERE email = #{email}
</select>
<update id="updateLastLogin">
UPDATE member SET last_login = now()
WHERE email = #{email}
</update>
</mapper>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<jsp:include page="../layout/header.jsp"></jsp:include>
<jsp:include page="../layout/nav.jsp"></jsp:include>
<!-- email, pwd, nick_name -->
<div class="container my-3">
<h4 class="mb-3">로그인</h4><br>
<form action="/member/login" method="post">
<div class="mb-3">
<label for="e" class="form-label">email</label>
<input type="email" name="email" class="form-control" id="e" placeholder="example@example.com">
</div>
<div class="mb-3">
<label for="p" class="form-label">Password</label>
<input type="password" name="pwd" class="form-control" id="p" placeholder="password">
</div>
<c:if test="${not empty param.errMsg}">
<div class="mb-3 text-danger" >
<c:choose>
<c:when test="${param.errMsg eq 'Bad credentials'}">
<c:set value="이메일과 비밀번호가 일치하지 않습니다." var="errText" />
</c:when>
<c:otherwise>
<c:set value="관리자에게 문의해주세요." var="errText" />
</c:otherwise>
</c:choose>
${errText}
</div>
</c:if>
<button type="submit" class="btn btn-primary">LogIn</button>
</form>
</div>
<jsp:include page="../layout/footer.jsp"></jsp:include>
nav.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="/">홈</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/board/list">드림</a>
</li>
<sec:authorize access="isAuthenticated()">
<sec:authentication property="principal.mvo.email" var="authEmail"/>
<sec:authentication property="principal.mvo.nickName" var="authNick"/>
<sec:authentication property="principal.mvo.authList" var="auths"/>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/board/register">글쓰기</a>
</li>
<c:choose>
<c:when test="${auths.stream().anyMatch(authVO -> authVO.auth.equals('ROLE_ADMIN')).get()}">
<li class="nav-item">
<a class="nav-link" href="/member/list">회원리스트 ${authNick }(${authEmail }/ADMIN)</a>
</li>
</c:when>
<c:otherwise>
<li class="nav-item">
<a class="nav-link" href="/member/modify">회원정보수정 ${authNick } (${authEmail })</a>
</li>
</c:otherwise>
</c:choose>
<li class="nav-item">
<a class="nav-link" href="" id="logoutLink">LogOut</a>
</li>
<form action="/member/logout" method="post" id="logoutForm">
<input type="hidden" name="email" value="${authEmail }">
</form>
</sec:authorize>
<sec:authorize access="isAnonymous()">
<li class="nav-item">
<a class="nav-link" href="/member/login">로그인</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/member/register">회원가입</a>
</li>
</sec:authorize>
</ul>
</div>
</div>
</nav>
<script type="text/javascript">
document.getElementById('logoutLink').addEventListener('click', (e)=>{
e.preventDefault();
document.getElementById('logoutForm').submit();
});
</script>
[Spring] 26. 로그인 / 로그아웃
(다음 게시물 예고편)
[Spring] 27. 게시물/댓글 - 작성자가 일치하면 수정/삭제
728x90
@rlozlr :: 얼렁뚱땅 개발자
얼렁뚱땅 주니어 개발자
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!