Hello

25. JWT를 위한 로그인 시도

by 볼빵빵오춘기

PrincipalDetails.java

auth 패키지 생성 후 PrincipalDetails.java 생성 후 코드 작성한다.

public class PrincipalDetails implements UserDetails{

    private User user;

    public PrincipalDetails(User user){
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        user.getRoleList().forEach(r -> {
            authorities.add(()->{ return r;});
        });
        return authorities;
    }
}

 

UserRepository.java - 인터페이스 생성 및 findByUsername() 작성

repository 패키지 생성 후 코드 작성한다.

public interface UserRepository extends JpaRepository<User, Long> {
    public User findByUsername(String username);
}

 

PrincipalDetailsService.java - 클래스 생성 및 코드 작성

// http://localhost:8080/login => 여기서 동작x
@Service
@RequiredArgsConstructor
public class PrincipalDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("PrincipalDetailsService - loadUserByUsername run");
        User userEntity = userRepository.findByUsername(username);
        return new PrincipalDetails(userEntity);
    }

}

 

JwtAuthenticationFilter.java

  • jwt 패키지 밑에 JwtAuthenticationFilter.java 생성한다.
  • UsernamePasswordAuthenticationFilter 을 extends 해준다.
  • 스프링 시큐리티에 UsernamePasswordAuthenticationFilter가 있다.
  • 그러면 언제 이 UsernamePasswordAuthenticationFilter필터가 동작하냐면 /login 요청해서 username, password를 post로 전송하면 UsernamePasswordAuthenticationFilter가 동작을 한다.
  • 현재는 Securityconfig.java 동작안하게끔 해놓았기 때문에 작동을 안한다.
  • 다시 Securityconfig.java JwtAuthenticationFilter 를 등록을 해주면 된다.
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

}

 

SecurityConfig.java - JwtAuthenticationFilter 필터 등록

@Override
protected void configure(HttpSecurity http) throws Exception {
//        http.addFilter(new MyFilter1()); // 에러
//        http.addFilterBefore(new MyFilter1(), BasicAuthenticationFilter.class); // 필터가 실행되는지 test
    http.addFilterBefore(new MyFilter3(), BasicAuthenticationFilter.class); // 필터1,2를 만들로 FilterConfig에서 만든 후 Security 필터가 먼저 실행되는지 아니면 내가 만든 필터가 먼저 실행되는지 test

    http
            .addFilter(corsFilter) // @CrossOrigin(인증x), 시큐리티 필터에 등록(인증o)
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .formLogin().disable()
            .httpBasic().disable()
            .addFilter(new JwtAuthenticationFilter()) // AuthenticationManager
            .authorizeRequests()
            .antMatchers("/api/v1/user/**")
            .access("hasRole('ROLE_USER') or hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
            .antMatchers("/api/v1/manager/**")
            .access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
            .antMatchers("/api/v1/admin/**")
            .access("hasRole('ROLE_ADMIN')")
            .anyRequest().permitAll();
}

 

JwtAuthenticationFilter.java - 넘겨받은 파라미터에 대한 코드 추가

jwt 패키지 밑에 JwtAuthenticationFilter.java 생성 후 코드 작성한다.

@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

//    public JwtAuthenticationFilter(){
//    }

    private final AuthenticationManager authenticationManager;

    // login 요청을 하면 로그인 시도를 위해서 실행되는 함수
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        System.out.println("JwtAuthenticationFilter login try");

        // 1. username, password를 받는다

        // 2. 정상인지 로그인 시도를 해본다.
        // authenticationManager로 로그인 시도를 하면 PrincipalDetailsService가 호출이 된다.  => loadUserByUsername()이 실행된다.

        // 3. PrincipalDetails를 세션에 담는다. (세션에 담는 이유는 권한관리를 하기 위해서이다.)

        // 4. JWT 토큰을 만들어서 응답해주면 된다.

        return super.attemptAuthentication(request, response);
    }
}

 

실행결과

 

블로그의 정보

Hello 춘기's world

볼빵빵오춘기

활동하기