이제 회원가입 로직을 완료했으니 로그인 기능을 구현하겠습니다.
먼저 시큐리티를 통해서 로그인을 성공하면 어느페이지로 이동 할 지 설정해줍니다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeRequests()
.requestMatchers("/login", "/signup", "/user","image/*","/check-username","/send-verification-code","/verify-code",
"/css/**", "/image/**", "/js/**","/","/main").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/main", true)
.and()
.logout()
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.and()
.csrf().disable()
.build();
}
저는 일단 로그인 성공 후 처리할 url을 /main으로 설정했습니다.
package org.zerock.wantuproject.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("main")
public String main() {
return "main";
}
}
그리고 난 뒤 간단하게 컨트롤러를 구성하였습니다.
그리고 데이터베이스에서 로그인을 할때 uid를 통해서 회원을 찾아 줄 서비스 로직을 구현하였습니다.
package org.zerock.wantuproject.service;
import lombok.RequiredArgsConstructor;
import org.hibernate.Hibernate;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zerock.wantuproject.entity.User;
import org.zerock.wantuproject.repository.UserRepository;
import static org.zerock.wantuproject.entity.QUser.user;
@RequiredArgsConstructor
@Service
public class UserDetailService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public User loadUserByUsername(String uid) throws UsernameNotFoundException {
return userRepository.findByUid(uid)
.orElseThrow(() -> new IllegalArgumentException((uid + " not found")));
}
}
그 뒤에 이제 html파일을 구성을 해줍니다.
login.html파일은 tymleaf를 통해 fragmets로 나누었습니다.
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로그인</title>
<!-- 부트스트랩 cdn -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- 부트스트랩 아이콘 cdn -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link th:href="@{css/basic.css}" rel="stylesheet">
<link th:href="@{css/login.css}" rel="stylesheet">
</head>
<body>
<!--<!– 헤더 영역 –>-->
<!--<th:block th:replace="fragments/nav :: header"></th:block>-->
<!--<!– SNB 영역 –>-->
<!--<th:block th:replace="fragments/nav :: navMenu"></th:block>-->
<!-- 메인 컨텐츠 영역 -->
<th:block th:replace="fragments/member/loginContent"></th:block>
<!-- 푸터 영역 -->
<th:block th:replace="fragments/nav :: footer"></th:block>
<!--<script th:src="@{js/login.js}"></script>-->
</body>
</html>
이렇게 하면 코드를 재사용 할 수가 있고 또한 페이지 이동시 동적으로 처리 할 수 있다는 장점이 있습니다.
나중에 더 자세하게 설명하겠습니다..
css는
/* 기본 설정 */
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
/* loginContent 전체를 Flexbox로 설정 */
.loginContent {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
/* 배경 이미지 설정 */
.background-image {
background-image: url('/image/loginbackground.png'); /* 실제 이미지 경로로 변경 */
background-size: cover;
background-position: center;
width: 100%;
height: 100vh;
display: flex;
justify-content: flex-end; /* 버튼을 아래로 밀어냄 */
align-items: center;
padding-bottom: 100px;
position: relative;
z-index: 1;
flex-direction: column;
}
/* 로그인 버튼 스타일 */
.login-button {
background-color: #f08080;
color: white;
border: none;
padding: 15px 40px;
border-radius: 30px;
cursor: pointer;
font-size: 18px;
z-index: 2;
}
/* 로그인 폼 스타일 */
.hidden {
display: none;
}
.login-form {
width: 550px;
padding: 30px;
background-color: white;
/* border: 1px solid #ddd; */
border-radius: 10px;
/* box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); */
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 100;
display: none;
height: 500px;
}
.login-form h2{
margin-bottom: 50px;
font-weight: bold;
margin-top: 40px;
}
.form-group{
display: flex;
flex-direction: row;
align-items: center;
width: 450px;
margin: 0 auto;
margin-bottom: 40px;
justify-content: space-between;
}
.form-group input{
width: 365px;
border: 1px solid black;
border-radius: 20px;
}
.form-group label{
font-weight: bold;
font-size: 20px;
}
.form-group-find{
display: flex;
justify-content: flex-end;
margin-top: -15px;
margin-bottom: 20px;
}
.find-id-password{
margin-right: 20px;
}
.form_button{
display: flex;
flex-direction: column;
}
.form-login-button{
width: 300px;
margin: 0 auto;
margin-bottom: 20px;
background-color: white;
border-radius: 15px;
padding: 6px;
font-size: 18px;
/* font-weight: bold; */
border: 1px solid black;
}
.form-register-button{
width: 300px;
margin: 0 auto;
margin-bottom: 20px;
background-color: white;
border-radius: 15px;
padding: 6px;
font-size: 18px;
/* font-weight: bold; */
border: 1px solid black;
color: black;
text-decoration: none;
}
.form-register-button:hover{
color: black;
}
.show {
display: block;
opacity: 0;
animation: fadeIn 1s forwards;
}
/* 애니메이션 */
@keyframes fadeIn {
0% {
opacity: 0;
transform: translate(-50%, -60%);
}
100% {
opacity: 1;
transform: translate(-50%, -50%);
}
}
이렇게 구성을 해놓았습니다. fadeIn애니메이션을 통해서 버튼을 누리면 화면에 로그인 폼이 나타나도록 구성하였습니다.
<!-- 메인 컨텐츠 영역 -->
<div class="loginContent">
<div class="background-image">
<button class="login-button" onclick="showLoginForm()">로그인/회원가입</button>
</div>
</div>
<!-- 로그인 폼 -->
<div id="loginForm" class="login-form hidden">
<h2>로그인</h2>
<form action="/login" method="POST">
<input type="hidden" th:name="${_csrf?.parameterName}" th:value="${_csrf?.token}" />
<div class="form-group">
<label for="username">아이디</label>
<input type="text" class="form-control" id="username" name="username" placeholder="아이디">
</div>
<div class="form-group">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password" placeholder="비밀번호">
</div>
<div class="form-group-find">
<div class="find-id-password"><a href="#">아이디 / 비밀번호 찾기</a></div>
</div>
<div class="form_button">
<button type="submit" class="form-login-button">로그인</button>
<a href="/signup" class="form-register-button">회원가입</a>
</div>
</form>
</div>
<script>
function showLoginForm() {
const loginForm = document.getElementById('loginForm');
loginForm.classList.remove('hidden'); // 폼을 보이게 하기
loginForm.classList.add('show'); // 애니메이션 효과 추가
}
</script>
로그인 페이지의 html의 컨텐츠 부분입니다.

실행화면 입니다
'project > 모임웹프로젝트' 카테고리의 다른 글
| 아이디 비밀번호 찾기 구현(11) (0) | 2024.09.30 |
|---|---|
| 로그인 기능 구현 중 UserDetails 관련 이슈 (10) (2) | 2024.09.30 |
| 모임 웹 프로젝트 회원가입 중복확인 (8) (0) | 2024.09.29 |
| 모임 웹 프로젝트 회원가입 아이디 중복검사 처리(7) (0) | 2024.09.29 |
| 모임 웹 프로젝트 회원가입 백엔드 구성 (6) (0) | 2024.09.29 |