UserDetailsService 인터페이스)
- 데이터베이스에서 회원 정보를 가져오는 역할
- loaduserByusername() 메소드가 존재하며, 회원 정보를 조회하여 사용자의 정보와 권한을 갖는 UserDetails 인터페이스를 반환
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;
MemberService.java
- loaduserByusername 매개변수가 email 되어있는데 이것은 SecurityConfig 에서 설정할 수 있다.
@Service
@Transactional
@RequiredArgsConstructor
public class MemberService implements UserDetailsService {
private final MemberRepository memberRepository;
public Member saveMember(Member member){
validateDuplicatemember(member);
return memberRepository.save(member);
}
public void validateDuplicatemember(Member member){
Member findMember = memberRepository.findByEmail(member.getEmail());
if(findMember != null){
throw new IllegalStateException("이미 가입된 회원입니다.");
}
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Member member = memberRepository.findByEmail(email);
if(member == null){
throw new UsernameNotFoundException(email);
}
return User.builder()
.username(member.getName())
.password(member.getPassword())
.roles(member.getRole().toString())
.build();
}
}
SecurityConfig .java
- 로그인 페이지 설정
- 로그인 성공시 경로 설정
- 로그인 시 사용될 파라미터 설정
- 로그인 실패시 경로 설정
- 로그아웃 URL 설정
- 로그아웃 성공시 경로 설정
- configure(AuthenticationManagerBuilder auth) : 스프링 시큐리에서 인증은 AuthenticationManager 를 통해 이루어지며 AuthenticationManagerBuilder 가 AuthenticationManager 를 생성한다.
userDetailService 를 구현하고 있는 객체로 memberService를 지정해주며, 비밀번호 암호화를 위해 passwordEncoder를 지정해준다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MemberService memberService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/members/login")
.defaultSuccessUrl("/")
.usernameParameter("email")
.failureUrl("/members/login/error")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/members/logout"))
.logoutSuccessUrl("/");
...
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(memberService)
.passwordEncoder(passwordEncoder());
}
...
}
thymeleaf-extras-springsecurity
- 권한에 따른 컨텐츠 보여주기
Github : https://github.com/thymeleaf/thymeleaf-extras-springsecurity
Docs : https://www.thymeleaf.org/doc/articles/springsecurity.html
<!-- thymeleaf-extras-springsecurity5 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
header.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<div class="collapse navbar-collapse" id="navbarsExample02">
<ul class="navbar-nav me-auto">
<li class="nav-item" sec:authorize="hasAnyAuthority('ROLE_ADMIN')">
<a class="nav-link active" aria-current="page" href="/admin/item/new">상품등록</a>
</li>
<li class="nav-item" sec:authorize="hasAnyAuthority('ROLE_ADMIN')">
<a class="nav-link" href="/admin/items">상품관리</a>
</li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a class="nav-link" href="/cart">장바구니</a>
</li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a class="nav-link" href="/orders">구매이력</a>
</li>
<li class="nav-item" sec:authorize="isAnonymous()">
<a class="nav-link" href="/members/login">로그인</a>
</li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a class="nav-link" href="/members/logout">로그아웃</a>
</li>
</ul>
SecurityConfig .java
- 특정주소 패턴들 접근 권한 부여
- 인증되지 않은 사용자가 리소스 접근시 수행되는 핸들러 등록
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/members/login")
.defaultSuccessUrl("/")
.usernameParameter("email")
.failureUrl("/members/login/error")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/members/logout"))
.logoutSuccessUrl("/");
http.authorizeRequests()
.mvcMatchers("/", "/members/**", "/item/**", "/images/**").permitAll()
.mvcMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
http.exceptionHandling()
.authenticationEntryPoint(new CustomAuthenticationEntryPoint());
}
SecurityConfig .java
- static 폴더의 하위 파일은 인증을 무시하도록 설정
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**");
}
'2022 > JPA입문(完)' 카테고리의 다른 글
상품 등록 (0) | 2022.02.04 |
---|---|
엔티티 관계도 / 엔티티 클래스 다이어그램 (0) | 2022.02.04 |
부트스트랩(bootstrap) 5.1 적용 (0) | 2022.01.24 |
스프링 시큐리티 - 1 (0) | 2022.01.23 |
Thymeleaf - 1 (0) | 2022.01.21 |