스프링 시큐리티 설정을 하자-(2) 로그인 검증 로직 구현

Alex·2025년 1월 16일
0

Plaything

목록 보기
77/118

이제 DB에 저장된 유저 정보를 load하는 부분을 만들어야 한다.

@RequiredArgsConstructor
@Service
public class CustomUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User userData = userRepository.findByLoginId(username).orElseThrow(() -> new CustomException(ErrorCode.NOT_EXIST_USER));

        //DTO에 넣어서 전달, 이 DTO는 UserDetails를 구현한 DTO로 직접 만들어야 함
        return new CustomUserDetails(userData);
    }
}



public class CustomUserDetails implements UserDetails {

    private final User user;

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

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new ArrayList<>();
        collection.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getRole().toString();
            }
        });

        return collection;
    }

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

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

JWT


설정파일을 수정한다



    //AuthenticationManager가 인자로 받을 AuthenticationConfiguraion 객체 생성자 주입
    private final AuthenticationConfiguration authenticationConfiguration;
    private final JWTProvider jwtProvider;

    public SecurityConfig(AuthenticationConfiguration authenticationConfiguration, JWTProvider jwtProvider) {

        this.authenticationConfiguration = authenticationConfiguration;
        this.jwtProvider = jwtProvider;
    }


        http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtProvider), UsernamePasswordAuthenticationFilter.class);
import java.util.Collection;
import java.util.Iterator;

@RequiredArgsConstructor
public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    private final JWTProvider jwtProvider;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        String userName = obtainUsername(request);
        String password = obtainPassword(request);

        //Authentication Mangager에 던지기 전에 DTO에 담아줘야 한다.

        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userName, password, null);

        return authenticationManager.authenticate(authToken);
    }

    //로그인 성공 시 실행하는 메소드
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) {
        CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal();
        String userName = customUserDetails.getUsername();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
        GrantedAuthority auth = iterator.next();

        String role = auth.getAuthority();
        String token = jwtProvider.createToken(userName, role);
        response.addHeader("Authorization", "Bearer " + token);

    }

    //로그인 실패시 실행하는 메소드
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {

        request.setAttribute("401", "Unauthorized");
    }

}

이제 JWT를 검증하자


@RequiredArgsConstructor
public class JWTFilter extends OncePerRequestFilter {
    private final JWTProvider jwtProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authorization = request.getHeader("Authorization");

        if (authorization == null || !authorization.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);

        }

        String token = authorization.split(" ")[1];

        //토큰 소멸 시간 검증

        if (jwtProvider.isExpired(token)) {
            filterChain.doFilter(request, response);
            return;
        }

        String username = jwtProvider.getUsername(token);
        String roleString = jwtProvider.getRole(token);

        Role role = roleString.equals("ROLE_USER") ? Role.ROLE_USER : Role.ROLE_ADMIN;

        User user = User.builder().loginId(username).role(role).build();
        CustomUserDetails customUserDetails = new CustomUserDetails(user);

        //스프링 시큐리티 인증 토큰 생성
        Authentication authToken = new UsernamePasswordAuthenticationToken(customUserDetails, null, customUserDetails.getAuthorities());
        //세션에 사용자 등록

        SecurityContextHolder.getContext().setAuthentication(authToken);
        filterChain.doFilter(request, response);


    }
}

필터까지 등록해준다.

profile
답을 찾기 위해서 노력하는 사람

0개의 댓글