본문 바로가기
프로젝트/Spring Boot 블로그프로젝트

[블로그프로젝트] 19. 시큐리티로 로그인하기

by dantriss 2023. 6. 9.

유튜브에서 블로그 만들기 프로젝트를 따라하면서 나의 스킬을 조금더 레벨업 하고자 한다.

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 키를 눌러 메서드들을 오버라이딩 해준다.

컨트롤+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을 이용해 값을 찾도록 작성한다.

해당 내용은 SELECT * FROM user WHERE username =1?; 와 같다.

 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());
                    }

 

새로운 스프링과 스프링 버전을 사용하고 있는 나는 해당부분을 추가하면 오히려 실행하면 에러가 발생한다.

 

 

실행 후 서버로 이동해서 로그인을 실행 해보면

회원가입할때 입력한 아이디와 비밀번호를 입력해보자

 

문제없이 로그인이 되고 로그인 성공시 "/"로도 이동해지는걸 확인할 수 있다.

 

 

그럼 나는 해쉬된 비밀번호를 비교하는 코드를 주석으로 막아놓았는데 아이디값만 일치하면 아무 비밀번호나 입력하면 로그인 되는거 아냐?

라고 할 수 있다.

 

그래서 다른 비밀번호를 입력해보자.

참고로 로그아웃도 시큐리티가 알아서 처리해준다.

 

비밀번호를 다르게 입력해보자

 

비밀번호가 일치하지 않으면 로그인이 되지 않고 다시 로그인화면으로 이동하는걸 확인할 수 있다.

댓글