Project

로그인 코드

haedal-uni 2022. 6. 18. 19:06
728x90

WebSecurityConfig

로그인 페이지 커스터마이징 

더보기

 

 

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    //private final AuthenticationFailureHandler UserLoginFailHandler;
    private final AuthenticationFailureHandler customFailureHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.headers().frameOptions().disable();

        http.authorizeRequests()
                // image 폴더를 login 없이 허용
                .antMatchers("/img/**").permitAll()

                // css 폴더를 login 없이 허용
                .antMatchers("/css/**").permitAll()

                // js 폴더를 login 없이 허용
                .antMatchers("/js/**").permitAll()

                // 회원 관리 URL 전부를 login 없이 허용
                .antMatchers("/user/**").permitAll()

                // h2-console URL 을 login 없이 허용
                .antMatchers("/h2-console/**").permitAll()

                // 그 외 모든 요청은 인증과정 필요
                .anyRequest().authenticated()
                .and() // 그리고
                .formLogin() // 로그인 폼은
                .loginPage("/user/login") // 로그인 페이지를 우리가 만든 페이지로 등록한다.
    //            .failureUrl("/user/login/error")
                .failureHandler(customFailureHandler)
                .defaultSuccessUrl("/")
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/user/logout")
                .permitAll();
    }

    @Bean //비밀번호 암호화를 위해 사용 - 시큐리티는 비밀번호가 암호화 되있어야 사용가능하다
    public BCryptPasswordEncoder encodePassword() {
        return new BCryptPasswordEncoder(); // 회원가입할때 쓰면된다.
    }
}

 

 

 

 

참고로 아래 코드는 작성안함 

    // 시큐리티가 대신 로그인해주는데 password를 가로채는데
    // 해당 password가 뭘로 해쉬화해서 회원가입이 되었는지 알아야
    // 같은 해쉬로 암호화해서 DB에 있는 해쉬랑 비교가능
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(principalDetailService).passwordEncoder(encodePWD());
    }

해당 글 꼭 참고하기!! >>  [Spring] 스프링 시큐리티 로그인

 

 

 

 

 

 

 

UserDetailsImpl 

세션에 등록될 type은 UserDetails

UserDetails을 extends해서 새로운 class인 UserDetailsImpl 을 만든다.

더보기

 

public class UserDetailsImpl implements UserDetails {

    private final User user;

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

    public User getUser() {
        return user;
    }

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

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

    //계정이 만료되지 않았는지 리턴 (true: 만료안됨)
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    // 계정이 잠겨있는지 않았는지 리턴. (true:잠기지 않음)
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    //비밀번호가 만료되지 않았는지 리턴한다. (true:만료안됨)
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    // 계정이 활성화(사용가능)인지 리턴 (true:활성화)
    @Override
    public boolean isEnabled() {
        return true;
    }

    // 계정이 갖고있는 권한 목록은 리턴
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.emptyList();
    }
}

 

 

로그인했을때 정보들

스프링 시큐리티가 로그인 요청을 가로채서 로그인을 진행하고 완료가 되면

UserDetails타입의 오브젝트를 스프링 시큐리티의 고유한 세션저장소에 저장을 해준다.

 

 

 

 

UserDetailsServiceImpl ( 로그인을 진행하는 Service )

@Service
public class UserDetailsServiceImpl implements UserDetailsService{

    @Autowired
    private UserRepository userRepository;

    //스프링이 로그인 요청을 가로챌때 username, password변수 2개를 가로채는데
    //password 부분 처리는 알아서처리,
    //username이 DB에 있는지 확인해줘야함
    
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("Can't find " + username));

        return new UserDetailsImpl(user);
    }
}

 

loadUserByUsername함수를 Override하여 DB에 접근해 username이 DB에 있는지 확인한다.

password는 알아서 처리된다.

유저정보가 있으면 UserDetails를 구현한 class를 해당 user의 정보로 초기화해주고 리턴해준다.

이후에 시큐리티의 세션의 정보가 저장이된다.

 

 

login.html

        <form class="signin" action="/user/login" method="post">
<!--        <form class="signin"  action="/auth/loginProc" method="post"> &lt;!&ndash;컨트롤러에 해당 주소 맵핑 안만들고 시큐리티가 가로채게 할것&ndash;&gt;-->
            <h1 class="signup1">SIGN IN</h1>
            <br><br><br><br>
            <input name="username" type="text" placeholder="아이디*" class="username" id="LoginUsername"/>

            <input name="password" type="password" placeholder="비밀번호*" class="username" id="LoginPw"/>

            <button id="signInBtn" class="btn" type="button" onclick="checkSignIn()">Get Started</button>

            <br><br><br><br>
        </form>

 

  • 로그인 요청 → 
  • loginPage()로 이동 → 
  • loginProcessingUrl이 가로챔 (username, password정보) → 
  • UserDetailsService의 loadUserByUsername로 던진다 → 
  • DB와 username을 비교 후 UserDetails를 반환함 → 
  • ( UserDetails를 반환하기전에 WebSecurityConfigurerAdapter를 상속받은 클래스에서   
    configure() 함수에서 패스워드 비교가 이뤄짐 ) → 
  • 정상인것을 확인 됐으면 스프링 시큐리티 영역에 등록된다.
  • 로그인되면 defaultSuccessUrl로 이동함 
  • 이제 세션이 만들어졌음

 

728x90

'Project' 카테고리의 다른 글

댓글 test 코드  (0) 2022.06.20
회원가입 코드  (0) 2022.06.19
웹소켓 - 상대방과 나 구분하기  (0) 2022.06.04
웹소켓 기본 코드  (0) 2022.06.03
paging test 코드 보기(검증x)  (0) 2022.05.27