점프 투 스프링부트를 참고하여 학습,작성하였습니다.
1.로그인 url 등록
스프링 시큐리티에 로그인을 하기 위한 URL을 수정한다.
.formLogin 메서드는 스프링 시큐리티의 로그인 설정을 담당하는 부분
Spring Security의 구성에서 .formLogin() 메서드를 호출
/user/login 경로를 사용하여 사용자 정의 로그인 페이지를 설정
로그인 성공 후 사용자를 리디렉션할 기본 URL 루트 경로로 설정
.formLogin((formLogin) -> formLogin
.loginPage("/user/login")
.defaultSuccessUrl("/"))
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
.csrf((csrf) -> csrf
.ignoringRequestMatchers(new AntPathRequestMatcher("/h2-console/**")))
.headers((headers) -> headers
.addHeaderWriter(new XFrameOptionsHeaderWriter(
XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)))
.formLogin((formLogin) -> formLogin
.loginPage("/user/login")
.defaultSuccessUrl("/"))
;
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
2.컨트롤러 URL 매핑
@PostMapping 방식의 메서드는 스프링 시큐리티가 대신 처리하므로
로그인페이지로 가는 GetMapping만 만들어준다.
@GetMapping("/login")
public String login() {
return "login_form";
}
3.템플릿 제작
로그인화면 템플릿을만든다.
<html layout:decorate="~{base}">
<div layout:fragment="content" class="container my-3">
<form th:action="@{/user/login}" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">사용자ID 또는 비밀번호를 확인해 주세요.</div>
</div>
<div class="mb-3">
<label for="username" class="form-label">사용자ID</label>
<input type="text" name="username" id="username" class="form-control">
</div>
<div class="mb-3">
<label for="password" class="form-label">비밀번호</label>
<input type="password" name="password" id="password" class="form-control">
</div>
<button type="submit" class="btn btn-primary">로그인</button>
</form>
</div>
네비게이션 바에 링크추가
<a class="nav-link" href="@{/user/login}">로그인</a>
4.유저 리포지토리 수정
ID를 조회하는 기능이 필요하기 때문에 findByusername 메서드를 추가한다.
package com.example.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.model.*;
import java.util.Optional;
public interface UserRepository extends JpaRepository<SiteUser, Long> {
Optional<SiteUser> findByusername(String username);
}
5.UserRole 파일 만들기
ADMIN은 ‘ROLE_ADMIN’, USER는 ‘ROLE_USER’라는 값을 부여했다.
package com.example.model;
import lombok.Getter;
@Getter
public enum UserRole {
ADMIN("ROLE_ADMIN"),
USER("ROLE_USER");
UserRole(String value) {
this.value = value;
}
private String value;
}
6.UserSecurityService 서비스 제작
스프링 시큐리티가 로그인 시 사용해야하므로 UserDetailsService인터페이스를 구현한다.
loadUserByUsername 메서드는 사용자명(username)으로 스프링 시큐리티의 사용자(User) 객체를 조회하고 리턴한다.
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class UserSecurityService implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<SiteUser> _siteUser = this.userRepository.findByusername(username);
if (_siteUser.isEmpty()) {
throw new UsernameNotFoundException("사용자를 찾을수 없습니다.");
}
SiteUser siteUser = _siteUser.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("admin".equals(username)) {
authorities.add(new SimpleGrantedAuthority(UserRole.ADMIN.getValue()));
} else {
authorities.add(new SimpleGrantedAuthority(UserRole.USER.getValue()));
}
return new User(siteUser.getUsername(), siteUser.getPassword(), authorities);
}
}
7.SecurityConfig Bean 추가
AuthenticationManager 빈은 스프링 시큐리티의 인증을 처리한다.
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
8.navbar 수정
로그인상태와 비로그인 상태를 체크하여 로그인,로그아웃 버튼이 보이게한다.
<a class="nav-link" sec:authorize="isAnonymous()" th:href="@{/user/login}">로그인</a>
<a class="nav-link" sec:authorize="isAuthenticated()" th:href="@{/user/logout}">로그아웃</a>
9.로그아웃기능 추가
SecurityConfig에 로그아웃 기능을 추가한다.
.logout((logout) -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true))
'BackEnd > SpringBoot' 카테고리의 다른 글
[Spring Boot] 글쓴이 항목 추가 (0) | 2024.07.05 |
---|---|
[오류][SpringBoot] sec:authorize 오류 (0) | 2024.07.05 |
[Spring Boot] 회원가입기능 (0) | 2024.07.05 |