본문 바로가기
공부/프로그래밍

[SpringBoot 2.x] 회원가입 할 때 이미 가입한 회원이면 로그인 + Auth 하기.

by demonic_ 2018. 7. 9.
반응형

해당 코드는 로그인 기능이 이미 만들어졌다는 가정하에 작성되었습니다.


환경

- Spring Boot 2.x

- Spring Security

- JPA

- MariaDB


요약

- 회원가입을 할때 해당 이메일(또는 ID)가 회원가입 되어있는지 확인

- (회원가입이 되어있는 계정이라면) 로그인한 계정에 세션 부여

- Authentication 에 유저정보 설정 (.authenticate 기능)



1. UserDetailsService 이 구현되어 있는지 확인

해당 클래스는 로그인할때 User 클래스를 생성하여 리턴하는 역할을 합니다.

여기서는 DB를 조회하여 해당 고객이 존재하는지 여부를 점검한 후 User 클래스에 생성하여 리턴합니다.

/**
 * [Spring Security] UserDetailsService 인터페이스 구현체
 */
@Service
public class CustomUserDetailService implements UserDetailsService {
    @Autowired
    private MemberRepository memberRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Member member = memberRepository.findByEmail(email);
        UserDetails user= new User(email, member.getPassword(), authorities(member));

        return user;
    }

    // Spring Security Role 설정
    private static Collection authorities(Member member){
        Collection authorities = new ArrayList<>();
        if(member.getEmail().equals("test@test.com")){
            authorities.add(new SimpleGrantedAuthority("ADMIN"));
        }else{
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        }
        return authorities;
    }
}




2. AuthenticationProvider 인터페이스를 구현합니다.

해당클래스를 통해 authentication 명령어로 Auth를 설정할 수 있습니다.

SpringBoot 1.x 버전에서는 AuthenticationManager 가 그역할을 했고 

@Autowired AuthenticationManager authenticationManager;

방식으로 주입받아서 authenticationManager.authentication 를 이용하는게 가능했으나

SpringBoot 2.x 부터는 안됩니다.

그래서 AuthenticationProvider 인터페이스를 구현하여 authentication 기능을 사용할 수 있도록 수정합니다.

/**
 * 회원가입 중 동일한 정보가 있는 경우 로그인 시키기 위해 사용
 * : Authtication 인증을 할 수 있도록 추가를 담당함
 */
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();

        // use the credentials
        // and authenticate against the third-party system
        return new UsernamePasswordAuthenticationToken(
                name, password, new ArrayList<>());
    }

    @Override
    public boolean supports(Class authentication) {
        return authentication.equals(
                UsernamePasswordAuthenticationToken.class);
    }
}



3. 회원가입하는 컨트롤러에 다음을 추가했습니다.

// Spring Security UserDetailsService 구현체
@Autowired
private CustomUserDetailService customUserDetailService;

// 회원가입 중 동일한 정보가 있는 경우 로그인 시키기 위해 사용되는 인터페이스
@Autowired
CustomAuthenticationProvider customAuthenticationProvider;

// 회원가입
@RequestMapping(path="/signup", method = RequestMethod.POST)
public String signup(@ModelAttribute Member member, HttpServletRequest request){
    PasswordEncoder pe = new BCryptPasswordEncoder();
    member.setPassword(pe.encode(member.getPassword()));

    // 기존에 가입되어 있는 고객인지 확인
    Member searchMember = memberRepository.findByEmail(member.getEmail());
    // 가입이 안되어 있다면 회원가입 시작.
    if (searchMember == null){
        memberRepository.save(member);
    }

    // 로그인 처리 진행
    // 세션처리
    sessionFactory.setSession(request, member.getEmail());
    // Auth 처리
    UserDetails userDetails = customUserDetailService.loadUserByUsername(searchMember.getEmail());
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(member.getEmail(), member.getPassword(), userDetails.getAuthorities());
    customAuthenticationProvider.authenticate(usernamePasswordAuthenticationToken);
    if (usernamePasswordAuthenticationToken.isAuthenticated()) {
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
    }

    return "redirect:/";
}



관련 코드는 깃헙에 올려두었습니다.

https://github.com/lemontia/SpringSecurityLogin

반응형

댓글