유튜브에서 블로그 만들기 프로젝트를 따라하면서 나의 스킬을 조금더 레벨업 하고자 한다.
IDE : IntelliJ
언어 : Java
DB : MySQL
빌드관리 도구 : Maven
OS : iOS
참고유튜브 : 메타코딩
이번 글에선 시큐리티를 이용해 로그인하는 과정을 정리하고자 한다.
loginForm.jsp 에서 form에 있는 주소를 변경하자.
아이디 저장기능도 사용안할 예정이기 때문에 삭제해준다.
<form action="/auth/loginProc" method="post">
<div class="form-group">
<label for="username">ID</label>
<input type="text" class="form-control" id="username" placeholder="Enter ID" name="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" placeholder="Enter Password" name="password">
</div>
<button id="btn-login" class="btn btn-primary">Login</button>
</form>
UserApiController.java에서 로그인 관련해서 작성하지 않았는데 어떻게 로그인을 진행할까?
바로 스프링시큐리티가 로그인정보를 가로채서 대신 로그인하게 처리할 것이다.
SecurityConfig.java로 이동해서 아래와 같이 코드를 추가한다.
.and()
.formLogin()
.loginPage("/auth/loginForm").permitAll()
.loginProcessingUrl("/auth/loginProc")
.defaultSuccessUrl("/")
logingProcessingUrl에서 주소를 추가해 loginForm에서 Username 과 password를 가지고 /auth/loginProc로 이동한다면 스프링시큐리티에서 해당 로그인을 가로채서 세션에 유저정보를 저장하여 대신 로그인하게 진행한다.
그리고 로그인이 성공했을때의 주소를 defaultSecuessUrl에 추가해준다.
다음으로 config 패키지 아래에 auth 폴더를 생성 후 principalDetail이라는 클래스를 생성하자
User 클래스를 컴포지션 해준 후
시큐리티 로그인을 위해서 userDetails 타입을 사용해야 하기 때문에 UserDetails를 상속해준다.
맥기준 ctrl+o 키를 눌러 메서드들을 오버라이딩 해준다.
getAuthrities는 맨 아래로 이동시켜준다.
유저정보값을 넣어줘야 하기 때문에 컴포지션해서 가져온 User클래스에서 password 와 username을 리턴으로 넣어준다.
그 외의 메서드들은 리턴값을 true 로 변경해준다.
아까맨 아래로 내린 메서드는 아래와 같이 작성해준다.
계정이 가지고 있는 권한목록을 리턴해주는데 Prefix로 "ROLE_"을 꼭 붙여줘야한다 규칙이라 이유는 없다.
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> collectors = new ArrayList<>();
collectors.add(()->{
return "ROLE_"+user.getRole();
}); //ROLE_USER가 리턴될 것 "ROLE_"을 붙이는건 규칙
return collectors;
}
auth패키지 아래에 PrincipalDetailService 클래스파일을 생성하고 UserRepository를 컴포지션을 해준다.
그 후 loadUserByUsername을 오버라이드 해준 후 userRepository로 이동해서 쿼리를 작성할 것이다.
UserRepository로 이동해 네이밍쿼리를 이용해 username을 이용해 값을 찾도록 작성한다.
Optional<User> findByUsername(String username);
다시 PrincipalDetailService.java로 이동해 마저 코드를 작성한다.
userRepository에 있는 findByUsername 메서드를 사용할 것이다.
리턴해줄때 principalDetail로 한번 감싸서 리턴을 해줄 것이다.
파라미터값으로 username값을 findByUsername에 보내주고 만약 일치하지 않는 아이디라면 해당아이디를 찾을 수 없다는 내용을 리턴해준다.
여기서 리턴해줄때 시큐리티세션에 유저정보가 저장이 된다.
해당 내용을 작성해주지 않는 다면 저번 글에서 작성한것처럼 id 에는 "user" password 는 콘솔에서 나오는 비밀번호를 입력해야한다.
"엇? 로그인할 때 입력하는건 username이랑 password 인데 파라미터로 비밀번호는 왜 안받고 안보내지?"
비밀번호 부분은 시큐리티가 알아서 처리해준다.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User principal = userRepository.findByUsername(username)
.orElseThrow(()->{
return new UsernameNotFoundException("해당 아이디 |'"+username+"|' 을 찾을 수 없습니다.");
});
return new PrincipalDetail(principal);
}
PrincipalDetail에서 user가 null 값이기 때문에 생성자를 추가해서 아래와 같이 만들어준다.
(생성자 생성 단축키 맥 윈도우 상관없이 ctrl+o)
public PrincipalDetail(User user) {
this.user = user;
}
springboot 3.0 이상인 경우엔 아래의 과정을 안해도 로그인을 할 수가 있다.
(이유는 모르겠다! 시큐리티가 알아서 해쉬된 비밀번호와 비교해서 db에서 꺼내오는것 같다.)
이제 해쉬되어 db에 저장된 비밀번호를 다시 풀어서 유저가 입력한 비밀번호와 일치하는지 비교해서 일치하는지 확인하는 작업이 필요하다.
아래의 코드를 추가해주자
@Bean
protected void hashedPwCheck(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(principalDetailService).passwordEncoder(encoder());
}
새로운 스프링과 스프링 버전을 사용하고 있는 나는 해당부분을 추가하면 오히려 실행하면 에러가 발생한다.
실행 후 서버로 이동해서 로그인을 실행 해보면
문제없이 로그인이 되고 로그인 성공시 "/"로도 이동해지는걸 확인할 수 있다.
그럼 나는 해쉬된 비밀번호를 비교하는 코드를 주석으로 막아놓았는데 아이디값만 일치하면 아무 비밀번호나 입력하면 로그인 되는거 아냐?
라고 할 수 있다.
그래서 다른 비밀번호를 입력해보자.
참고로 로그아웃도 시큐리티가 알아서 처리해준다.
비밀번호가 일치하지 않으면 로그인이 되지 않고 다시 로그인화면으로 이동하는걸 확인할 수 있다.
'프로젝트 > Spring Boot 블로그프로젝트' 카테고리의 다른 글
[블로그프로젝트] 20. 글작성하기 (2) | 2023.06.11 |
---|---|
[블로그프로젝트] 19-1. 시큐리티세션에 저장된 아이디값 확인해보기 (0) | 2023.06.09 |
[블로그프로젝트] 18. 비밀번호 해쉬 후 회원가입하기 (0) | 2023.06.07 |
[블로그프로젝트] 17. 스프링시큐리티 로그인 커스터마이징 (2) | 2023.06.07 |
[블로그프로젝트] 16 스프링시큐리티로 로그인하기(3) (0) | 2023.06.05 |
댓글