단 하나의 맥락
: 회원가입 form으로 가입 후, 로그인 로그아웃 authorize 구현
Semiflow Bundle
: 로그인 URL 등록
: 컨트롤러에 매핑
: 로그인 템플릿 작성
: 리포지터리에 사용자 조회 메서드 선언
: 권한 부여
: 로그인 처리를 위한 UserSecurityService 작성
: SecurityConfig에 UserSecurityService 등록
: 로그인 링크를 네비게이션 바에 등록
: 로그인으로 Authenticated되었으면 로그인 버튼을 로그아웃 버튼으로 변경
: SecurityConfig에 로그아웃 URL 처리
로그인 URL 등록
> SecurityConfig에서
XFrameOptionsHeaderWriter 하단
- .and()
- .formLogin()
- .loginPage("/user/login")
- .defaultSuccessUrl("/")
- ;
작성
-
로그인 URL 매핑 추가
> UserController에서
- @GetMapping("/login")
- M : public String login() {}
- A1 : return "login_form";
작성
템플릿만 렌더링하고,
실제 로그인을 진행하는 PostMapping Method는 스프링 시큐리티가 대신 처리하므로, 구현하지 않아도 된다
-
로그인 템플릿 작성
> login_form.html 신규 작성
외부 플러그인
- <html layout:decorate="~{layout}"></html> 내부
- <div layout:fragment="content" class="container my-3"></div>
폼 형식
- <form th:action="@{user/login}" method="post"></form> 내부 최상단
- <div th:if="${param.error}"></div> 내부
- <div class="alert alert-danger">사용자 ID 또는 비밀번호를 확인해주세요</div> 로 err msg 구현
- <button type="submit" class="btn btn-primary">로그인</button> 최하단에 구현
로그인
- <div class="mb-3"></div> 내부
- <label for="username" class="form-label">사용자 ID</label>
- <input type="text" name="username" id="username" class="form-control">
로그아웃
- <div class="mb-3"></div> 내부
- <label for="password" class="form-label">비밀번호</label>
- <input type="password" name="password" id="password" class="form-control">
-
사용자 조회를 위해 리포지터리에 메서드 추가
> UserRepository에
- public interface UserRepository extends JpaRepository<SiteUser, Long> { }
- Optional<SiteUser> findByusername(String username); 추가
// import java.util.Optional
-
인증 후 사용자에게 부여할 권한을 USER, ADMIN 2가지로 관리
> UserRole.java 신규작성
- @Getter
- public enum UserRole {}
- P1 : ADMIN("ROLE_ADMIN"),
- P2 : USER("ROLE_USER");
- M : UserRole(String value) { }
- this.value = value;
- P3 : private String value;
-
UserDetailsService 인터페이스 구현하여 로그인 처리
> UserSecurityService 신규 작성
@Service
@RequriedArgsConstructor
public class UserSercurityService implements UserDetailsService {}
- P1 : private final UserRepository userRepository;
- @Override
- M : public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {}
- A1 : Optional<SiteUser> _siteUser = this.userRepository.findByusername(username);
- A2 : if (_siteUser.isEmpty()) { throw new UsernameNotFoundException("사용자를 찾을 수 없습니다"); }
- A3 : SiteUser siteUser = _siteUser.get();
- A4 : List<GrantedAuthority> authorities = new ArrayList<>();
- A5 :
- if ("admin".equals(username)) {
- authorities.add(new SimpleGrantedAuthority(UserRole.ADMIN.getValue()));
- } else {
- authorities.add(new SimpleGrantedAuthority(UserRole.USER.getValue())); }
- if ("admin".equals(username)) {
- A6 : return new User(siteUser.getUsername(), siteUser.getPassword(), authorities);
// 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;
-
스프링 시큐리티에 UserSecurityService 등록
> SecurityConfig에서
- P1 : private final UserSecurityService userSecurityService; 추가
- @Bean
- M : public AuthenticationManager authenticationManager
- S : (AuthenticationConfiguration authenticationConfiguration)
- HE : throws Exception {}
- A1 : return authenticationConfiguration.getAuthenticationManager();
// class에 @RequiredArgsConstructor 추가
// import com.mysite.sbb.user.UserSecurityService; 필요
// import org.springframework.security.authentication.AuthenticationManager;
// import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
-
로그인 링크를 네비게이션 바에 추가
> navbar.html 에서
- <li class="nav-item"></li> 사이
- <a class="nav-link" th:href="@{/user/login}">로그인</a>
-
인증 여부를 사용하여 로그인/로그아웃 버튼 조절
> navbar.html 에서
- <li class="nav-item"></li> 사이
- <a class="nav-link" sec:authorize="isAnonymous()" th:href="@{/user/login}">로그인</a>
- <a class="nav-link" sec:authorize="isAuthenticated()" th:href="@{/user/logout}">로그아웃</a>
로 위상별 표시
-
로그아웃 구현하기
> SecurityConfig에서
- .and()
- .logout()
- .logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
- .logoutSuccessUrl("/")
- .invalidateHttpSession(true)
- ;
추가
'포트폴리오 > SPRINGBOOT 옛날' 카테고리의 다른 글
3 - 09 : 글쓴이 표시 (0) | 2022.10.10 |
---|---|
3-08 : entity에 author 추가하기 (0) | 2022.10.10 |
3-06 : 회원가입 (0) | 2022.10.09 |
3-05 : spring security (3) | 2022.10.09 |
3-04 : 답변 갯수 표시 (0) | 2022.10.09 |