- SecurityConfiguration
회원정보는 회원이 로그인 한 후에만 보여져야 할 때 시큐리티 설정
현재 등록과 이메일권한 페이지만 허용해주었고 나머지는 허용하지 않았기에 다른 페이지는 로그인 창이 뜬다
@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//페이지 권한설정
http.authorizeHttpRequests()
.antMatchers(
"/"
, "/member/register"
, "/member/email-auth"
)
.permitAll(); // 지정한 권한을 모두 허용하겠다
http.formLogin() // 로그인 관련설정
.loginPage("/member/login")
.failureHandler(null) // 로그인 실패시 처리하는 곳
.permitAll();
super.configure(http);
}
- UserAuthenticationFailureHandeler
failureHandler를 구현하기 위한 클래스
public class UserAuthenticationFailureHandeler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
// 에러가 발생했으니 request에 에러 메세지를 넣을 거임
setUseForward(true);
setDefaultFailureUrl("/member/login?error=true");
request.setAttribute("errorMessage", "로그인 실패!");
super.onAuthenticationFailure(request, response, exception);
}
}
그 후
- SecurityConfiguration 에 failureHandler 로그인 실패처리 메서드를 넣고 빈을 등록해준다
@Bean
UserAuthenticationFailureHandeler getFailureHandeler(){
return new UserAuthenticationFailureHandeler();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//페이지 권한설정
http.authorizeHttpRequests()
.antMatchers(
"/"
, "/member/register"
, "/member/email-auth"
)
.permitAll(); // 지정한 권한을 모두 허용하겠다
http.formLogin() // 로그인 관련설정
.loginPage("/member/login")
.failureHandler(getFailureHandeler()) // 로그인 실패시 처리하는 곳
.permitAll();
super.configure(http);
}
- UserDetails
UserDetailsService 인터페이스는 DB에서 유저 정보를 가져오는 역할을 한다
Spring Security에서 사용자의 정보를 담는 인터페이스는 UserDetails 인터페이스이다. 우리가 이 인터페이스를 구현하게 되면 Spring Security에서 구현한 클래스를 사용자 정보로 인식하고 인증 작업을 한다.
먼저 MemberService에서 UserDetailService를 상속받고 구현해준다
public interface MemberService extends UserDetailsService {
boolean register(MemberRequestDto requestDto);
// uuid에 해당하는 계정을 활성화
boolean emailAuth(String uuid);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Member> optionalMember = memberRepository.findById(username);
if(!optionalMember.isPresent()){
throw new UsernameNotFoundException("회원정보가 존재하지 않습니다");
}
Member member = optionalMember.get();
// return 객체의 파라미터가 이름, 비밀번호 , role인데 role은 직접 설정해야함
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(member.getUserName(), member.getPassword(),grantedAuthorities);
}
}
스프링 시큐리티에서 원하는 것은 id,pw,role 이니 해당값을 반환타입인 User에 담아서 리턴해준다
- SecurityConfiguration
마지막으로 passwordEncoder 생성
// MemberService를 시큐리티에 알려주기 위한 메서드
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(memberService)
.passwordEncoder(getPasswordEncoder());
super.configure(auth);
}
현재 로그인까지 구현되었지만 막상 서버를 실행하고 로그인을 하면 로그인이 되질 않는다
그 이유는 비밀번호를 암호화를 시켰기 때문에 현재 설정된 번호인 123을 쳐도 처리가 되지 않는것
그렇기에 SecurityConfiguration에서 썻던 방식대로 service단에 저장을 해야한다
@Override
public boolean register(MemberRequestDto requestDto) {
Optional<Member> validation = memberRepository.findById(requestDto.getUserId());
if(validation.isPresent()){
return false;
}
// BCrypt로 암호화하는 과정
String encPassword = BCrypt.hashpw(requestDto.getPassword(), BCrypt.gensalt());
String uuid = UUID.randomUUID().toString();
Member member = Member.builder()
.userId(requestDto.getUserId())
.userName(requestDto.getUserName())
.phone(requestDto.getPhone())
.password(encPassword)
.regDt(LocalDateTime.now())
.emailAuthYn(false)
.emailAuthKey(uuid)
.build();
memberRepository.save(member);
- MemberController
@RequestMapping("/member/login")
public String login(){
return "/member/login";
}
+) RequestMapping(요청 매핑) 이란?
요청이 왔을 때 어떤 컨트롤러가 호출이 되어야 하는지 알려주는 지표 같은 것이다.
@RequestMapping(value = "/hello-basic"
이렇게 매핑을 하면 localhost:8080/hello-basic으로 url을 입력했을 경우에 이것에 해당하는 메서드가 실행된다.
로그아웃
- SecurityConfiguration
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/member/logout"))
.logoutSuccessUrl("/") // 로그아웃되면 이동하는 페이지
.invalidateHttpSession(true); // 세션초기화
이메일 인증을 받지 못한 사람 구분
- MemberServiceImpl
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Member> optionalMember = memberRepository.findById(username);
if(!optionalMember.isPresent()){
throw new UsernameNotFoundException("회원정보가 존재하지 않습니다");
}
Member member = optionalMember.get();
// 이메일 인증절차에 관한 로직
// true가 아닐때 예외처리
if(!member.isEmailAuthYn()){
throw new MemberNotEmailAuthException("이메일 활성화 이후에 로그인 진행해주세요");
}
// return 객체의 파라미터가 이름, 비밀번호 , role인데 role은 직접 설정해야함
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(member.getUserName(), member.getPassword(),grantedAuthorities);
}
- MemberNotEmailAuthException
에러 execption을 만들어준다, 여기서 발생한 에러는 failureHandler로 갈 것이기에 어떤 에러가 발생했는지 작성한다
public class MemberNotEmailAuthException extends RuntimeException {
public MemberNotEmailAuthException(String error) {
super(error);
}
}
- UserAuthenticationFailureHandeler
public class UserAuthenticationFailureHandeler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String msg = "로그인에 실패!!";
if (exception instanceof InternalAuthenticationServiceException){
msg = exception.getMessage();
}
// 에러가 발생했으니 request에 에러 메세지를 넣을 거임
setUseForward(true);
setDefaultFailureUrl("/member/login?error=true");
request.setAttribute("errorMessage", "로그인 실패!");
super.onAuthenticationFailure(request, response, exception);
}
}
이후 로그인이나 회원정보 페이지를 들어가려면 회원가입이 되었다 하더라도 이메일 유저인증을 통해야만 입장할 수 있다
'개인프로젝트(수강프로그램)' 카테고리의 다른 글
회원목록 (0) | 2022.04.18 |
---|---|
관리자 로그인 (0) | 2022.04.16 |
비밀번호 초기화 요청 및 메일 링크를 통한 초기화 (0) | 2022.04.15 |
스프링부트 프로젝트(회원가입 및 인증메일) (0) | 2022.04.12 |
항해 99 7주차 회고(WIL) (0) | 2021.11.01 |